JService
A small and powerful pure javascript DI container that is non-opinionated, no automatic dependency resolution, and with scoping such as Singleton, Scoped and Transient. Can optionally integrate with any Node web frameworks that supports middleware, like Express, Koa, Fasify, etc.
Manual Resolution
Does NOT require to configure which dependencies to resolve automatically into the function or class, but instead, only a single provider
object is passed (that can resolve services). It's like manual resolution, but with cleaner parameter signature.
Integrates with Web Frameworks
Directly infuse web frameworks with dependency injection without changing the middleware's function signature.
Scoping
- Singleton - services are the same across providers
- Scoped - services are the same within the provider but different on another instance of provider
- Transient - services are always different even within the same provider
Declaration & Configuration
Isolate dependency declaration and configuration into a single file. Giving more control and ensure no implicit dependencies are leaked in.
Install
npm install jservice
Basic Usage
Using the core container without a web framework.
var JService = var DbService = var UserService = // Create a containervar jservice = JService// or var jservice = new JService() // Add add services to container { // DbService is a class or function constructor services services} // Build servicesjservice // Resolve service via providervar db = jserviceproviderdbBooks
Basic Integration Usage
Easily integrate with any web framework using middleware.
var JService = var express = var app = var registry = var IncomingMessage = // Create container with registry functionvar jservice = JService // Infuse jservice to express through middlewareapp // Signup endpointapp // Start server when jservice is readyjservicestart
Creating Services
A service can be a class, function, or concrete object. You basically don't need to do or set anything in the service. However, there are some options you can take, like explicitly putting the name and hook to startup events.
Basic ES5 service user.js
, with no name and hooks using functional programming (vanilla service).
{ // Injecting database service var db = provider // Exposed methods return { return dbUser } }moduleexports = User
Basic ES6 service database.js
with name and hooks using class.
{ thisURL = configurl thisUser = mongoose } { return mongoose }
Registering Services
Create a file registry.js
and add all the services.
var Database = var User = // more service ... module { services services services services // alias for singleton // We can also add a service multiple times but need to set different name services services // more services... // Some services can be configured, like this services}
There are several ways to add registry
// 1st optionvar jservice = registry// 2nd optionvar jservice = JService// 3rd optionvar jservice = jservice// 4th optionvar jservice = JServicejservicejservice
Service Scoping & Samples
In sample folder, you'll find various web framework integration samples and scope testing.
Notice the output ids generated when getting services. Same ids means the same instance.
- Singleton services have same id across providers
- Scoped services have same id within the request but different on subsequent request
- Transient services are always different (new instance)
GLOBAL SERVICE PROVIDERSingleton | plgcGPuZu SCOPED PROVIDER A Singleton | plgcGPuZuSingleton | plgcGPuZuScoped | 8YG0POVDjRScoped | 8YG0POVDjRTransient | ZAoy3AJoocTransient | ok1MP0cYir SCOPED PROVIDER B Singleton | plgcGPuZuSingleton | plgcGPuZuScoped | TQPz6T_SukScoped | TQPz6T_SukTransient | sPsB8hnC3UTransient | 8iz9mz8bC9
You check out the sample and run it yourself.
git clone <repo>npm installnpm run sample
API
Container (JService)
const JService = const container = JService // Or "new JService()"
Properties
.collection Collection
- service storage (add or disable services)
.provider Provider
- service injector (get services)
.isReady Boolean
- when start method is done
Methods
.build(registry)
Build up the container. Requires registry function that accepts the services Collection
.
container
.init(prototype, opt = {}) | returns middleware
Binds JService to any web frameworks that supports middleware. Check out the samples folder for supported frameworks and sample usage.
const express = const IncomingMessage = const app = appjservicestart
.start()
Starts the container, triggering all services that hooks to start event.
.createContainer() | returns new Container
Creates a sub-container that inherits all services from parent container.
const container = JServiceconst subContainer = container
.createProvider() | return new Provider
Create a scoped provider.
Collection
.singleton(service, name = null, deps = null)
Alias: .add(...)
Adds a singleton service to collection. Can omit name (string)
if the service contains static property service = <name>
. Can also filter or customize dependencies available for the service using deps (function)
services // Custom 3rd party vanilla servicesservics
.transient(service, name = null, deps = null)
Adds a transient mode service.
.scoped(service, name = null, deps = null)
Adds a scoped mode service.
.configure(name, config)
Configure a service. The name
can be either string or function service, to identify which service to configure. The config
is a function.
services
.enable(name, yes = true)
Enable/disable a service.
Provider
.create(deps)
Creates a sub (filtered) provider that only contains dependencies in deps
.service(name)
Alias: .get(name)
Strictly get a service. Throws error if service is not found.
.serviceOrNull(name)
Alias: .getOrNull(name)
Softly get a service. Will NOT throw error, but instead returns null
.
Mocking
const mock = // Import service to mockconst User = { } // Mock a provider with fake dependenciesconst provider = // Create instance of user service to testprovider
License
MIT License Copyright (c) 2019 RhaldKhein