null
if not in the container.ServiceIdentifier
.npm install service-composition
NOTE: The following examples use TypeScript, but its possible to use
service-composition
in JavaScript (without decorators) as well. See below for examples
ihelloservice.ts
import { ServiceIdentifier } from "service-composition";
const const IHelloService = ServiceIdentifier.create<IHelloService>("IHelloService");
export interface IHelloService {
sayHello(name: string): string;
}
itranslateservice.ts
import { ServiceIdentifier } from "service-composition";
const const ITranslateService = ServiceIdentifier.create<ITranslateService>("ITranslateService");
export interface ITranslateService {
format(message: string, args: Record<string, any>): string;
}
helloservice.ts
import { IHelloService } from "./ihelloservice";
import { ITranslateService } from "./itranslateservice";
export class HelloService implements IHelloService {
constructor(@ITranslateService private translate: ITranslateService) {
}
sayHello(name: str) {
return this.translate.format("hello, {name}", { name });
}
}
app.ts
import { ServiceCollection } from "service-composition";
// service interfaces
import { IHelloService } from "./ihelloservice";
import { ITranslateService } from "./itranslateservice";
// concrete services (or mock services for testing)
import { HelloService } from "./helloservice";
const serviceCollection = new ServiceCollection();
// define factories
serviceCollection.setClass(IHelloService, HelloService);
// define instances
serviceCollection.setInstance(ITranslateService, {
format(message: string, args: Record<string, any>) {
return message.replace(/\{([\w\d_$]+)\}/g, (_, key) => key in args ? args[key] : _);
}
});
// create container
const serviceProvider = serviceCollection.createContainer();
// resolve dependencies and get instances
const helloService = serviceProvider.getService(IHelloService);
console.log(helloService.sayHello("Alice")); // prints: hello, Alice
ihelloservice.js
const { ServiceIdentifier } = require("service-composition");
/** @type {ServiceIdentifier<IHelloService>} */
exports.IHelloService = ServiceIdentifier.create("IHelloService");
/**
* @typedef IHelloService
* @property {(name: string) => string} sayHello
*/
itranslateservice.js
const { ServiceIdentifier } = require("service-composition");
/** @type {ServiceIdentifier<ITranslateService>} */
exports.ITranslateService = ServiceIdentifier.create("ITranslateService");
/**
* @typedef ITranslateService
* @property {(message: string, args: Record<string, any>) => string} format
*/
helloservice.js
const { ITranslateService } = require("./itranslateservice.js")
class HelloService {
/**
* @param {import("./translateservice").ITranslateService} translate
*/
constructor(translate) {
this.translate = translate;
}
/**
* @param {string} name
*/
sayHello(name) {
return this.translate.format("hello, {name}", { name });
}
}
// Call decorator directly
ITranslateService(HelloService, undefined, /*parameterIndex*/ 0);
exports.HelloService = HelloService;
app.js
const { ServiceCollection } = require("service-composition");
// service interfaces
const { IHelloService } = require("./ihelloservice");
const { ITranslateService } = require("./itranslateservice");
// concrete services (or mock services for testing)
const { HelloService } = require("./helloservice");
const serviceCollection = new ServiceCollection();
// define factories
serviceCollection.setClass(IHelloService, HelloService);
// define instances
serviceCollection.setInstance(ITranslateService, {
format(message, args) {
return message.replace(/\{([\w\d_$]+)\}/g, (_, key) => key in args ? args[key] : _);
}
});
// create container
const serviceProvider = serviceCollection.createContainer();
// resolve dependencies and get instances
const helloService = serviceProvider.getService(IHelloService);
console.log(helloService.sayHello("Alice")); // prints: hello, Alice
interface ServiceIdentifier
— Identifies a service within the composition graph, and is a decorator thatserviceName
— Gets the (optional) name of the service.namespace ServiceIdentifier
— Methods used to get/create ServiceIdentifier
instances.
create(name?: string | symbol)
— Creates a unique service identifier, which can act as afunction optional(id)
— A decorator that indicates the provided ServiceIdentifier
is an optional dependency.function many(id)
— A decorator that indicates the provided ServiceIdentifier
is an n-ary dependency.enum ServiceDependencyCardinality
— Describes the cardinality of a ServiceDependency
:
ZeroOrOne
— The dependency may have at most one service.ExactlyOne
— The dependency may have exactly one service.ZeroOrMore
— The dependency may have any number of services.interface ServiceDependency
— Describes a dependency on a class.
id
— The ServiceIdentifier
that satisfies this dependency.parameterIndex
— The constructor parameter this dependency satisfies, if this describes a parameter.propertyName
— The name of the property (i.e., field) this dependency satisfies, if this describes a property.cardinality
— The cardinality of the dependency.namespace ServiceDependency
:
store(id, target, parameterIndex, cardinality)
— Stores information about a ServiceDependency
for a constructor parameter.store(id, target, propertyName, cardinality)
— Stores information about a ServiceDependency
for a property/field on an instance.get(target)
— Gets the ServiceDependencies
for a class.isParameterDependency(dependency)
— Tests whether a ServiceDependency
is for a constructor parameter.isPropertyDependency(dependency)
— Tests whether a ServiceDependency
is for an instance field/property.class ServiceDescriptor
— Describes how a service should be activated.
static forClass(ctor, staticArguments, supportsDelayedInstantiation)
— Creates a ClassDescriptor
for a class with the provided bound arguments and whether the result can be created as a Proxy
for circular dependencies.static forInstance(value)
— Creates an InstanceDescriptor
for a value.abstract activate(dependencies)
— Instantiates a service from the descriptor.class ClassDescriptor
— A ServiceDescriptor
describing a class.
bind(...args)
— Binds additional static arguments to a ClassDescriptor
.activate(dependencies)
— Instantiates a service from the descriptor.class InstanceDescriptor
— A ServiceDescriptor
describing an instance.
activate(dependencies)
— Instantiates a service from the descriptor.class ServiceCollection
— A catalog that maps a ServiceIdentifier
to a ServiceDescriptor
.
new ServiceCollection(entries?)
— Creates a new ServiceCollection
.get size()
— Returns the number of entries in the collection.has(id)
— Returns whether a ServiceIdentifier
is present in the collection.get(id)
— Gets the ServiceDescriptor
associated with a ServiceIdentifier
.set(id, descriptor)
— Sets the ServiceDescriptor
or an array of ServiceDescriptor
objects to use for a ServiceIdentifier
.setInstance(id, value)
— Shorthand for col.set(id, ServiceDescriptor.forInstance(value))
.setClass(id, ctor, staticArguments, supportsDelayedInstantiation?)
— Shorthand for col.set(id, ServiceDescriptor.forClass(ctor, staticArguments, supportsDelayedInstantiation))
.add(id, descriptor)
— Adds a ServiceDescriptor
or an array of ServiceDescriptor
objects to use for a ServiceIdentifier
(similar to col.set
, except it appends to the list of descriptors).addInstance(id, value)
— Shorthand for col.add(id, ServiceDescriptor.forInstance(value))
.addClass(id, ctor, staticArguments, supportsDelayedInstantiation?)
— Shorthand for col.add(id, ServiceDescriptor.forClass(ctor, staticArguments, supportsDelayedInstantiation))
.createContainer(parent?)
— Creates a ServiceContainer
with an optional parent.interface IServiceProvider
— Describes the shape of a service provider.const IServiceProvider
— A ServiceIdentifier
for an IServiceProvider
.class ServiceContainer
— Instantiates and holds references to services described in a ServiceCollection
. Every ServiceContainer
has a single IServiceProvider
dependency of itself.
new ServiceContainer(services)
— Creates a new ServiceContainer
from a ServiceCollection
.createInstance(descriptor, ...args)
— Instantiates a ClassDescriptor
or class with the provided static arguments.hasService(serviceId)
— Tests whether the provided ServiceIdentifier
can be instantiated by the container.getServices(serviceId)
— Instantiates services for the provided ServiceIdentifier
(when not already instantiated) and returns an array of all instantiated services.getService(serviceId)
— Instantiates the service for the provided ServiceIdentifier
(when not already instantiated) and returns it. Throws an error if there is not exactly one service for the provided ServiceIdentifier
.tryGetService(serviceId)
— Instantiates the service for the provided ServiceIdentifier
(when not already instantiated) and returns it if it was defined. Throws an error if there is more than one service for the provided ServiceIdentifier
.createChild(services)
— Creates a child container for this container's services and the provided ServiceCollection
.This package depends on the following packages at runtime:
@esfx/iter-fn
- For enhanced iteration.@esfx/lazy
- For lazy initialization of classes.graphmodel
- For managing the composition graph.tslib
- For TypeScript runtime helpers.This package is licensed under the MIT License.
This package is partially based on the dependency injection system used by VS Code, but with substantial changes in implementation. Please review THIRD_PARTY_NOTICES for more information.