@inversifyjs/container
Version:
InversifyJs container
339 lines • 14.7 kB
JavaScript
import { stringifyServiceIdentifier, } from '@inversifyjs/common';
import { bindingScopeValues, bindingTypeValues, getClassMetadata, ResolvedValueElementMetadataKind, } from '@inversifyjs/core';
import { getBindingId } from '@inversifyjs/core';
import { BindingConstraintUtils } from '../../container/binding/utils/BindingConstraintUtils.js';
import { InversifyContainerError } from '../../error/models/InversifyContainerError.js';
import { InversifyContainerErrorKind } from '../../error/models/InversifyContainerErrorKind.js';
import { buildBindingIdentifier } from '../calculations/buildBindingIdentifier.js';
import { isAnyAncestorBindingConstraints } from '../calculations/isAnyAncestorBindingConstraints.js';
import { isAnyAncestorBindingConstraintsWithName } from '../calculations/isAnyAncestorBindingConstraintsWithName.js';
import { isAnyAncestorBindingConstraintsWithServiceId } from '../calculations/isAnyAncestorBindingConstraintsWithServiceId.js';
import { isAnyAncestorBindingConstraintsWithTag } from '../calculations/isAnyAncestorBindingConstraintsWithTag.js';
import { isBindingConstraintsWithName } from '../calculations/isBindingConstraintsWithName.js';
import { isBindingConstraintsWithNoNameNorTags } from '../calculations/isBindingConstraintsWithNoNameNorTags.js';
import { isBindingConstraintsWithTag } from '../calculations/isBindingConstraintsWithTag.js';
import { isMultipleResolvedValueMetadataInjectOptions } from '../calculations/isMultipleResolvedValueMetadataInjectOptions.js';
import { isNoAncestorBindingConstraints } from '../calculations/isNoAncestorBindingConstraints.js';
import { isNoAncestorBindingConstraintsWithName } from '../calculations/isNoAncestorBindingConstraintsWithName.js';
import { isNoAncestorBindingConstraintsWithServiceId } from '../calculations/isNoAncestorBindingConstraintsWithServiceId.js';
import { isNoAncestorBindingConstraintsWithTag } from '../calculations/isNoAncestorBindingConstraintsWithTag.js';
import { isNotParentBindingConstraints } from '../calculations/isNotParentBindingConstraints.js';
import { isNotParentBindingConstraintsWithName } from '../calculations/isNotParentBindingConstraintsWithName.js';
import { isNotParentBindingConstraintsWithServiceId } from '../calculations/isNotParentBindingConstraintsWithServiceId.js';
import { isNotParentBindingConstraintsWithTag } from '../calculations/isNotParentBindingConstraintsWithTag.js';
import { isParentBindingConstraints } from '../calculations/isParentBindingConstraints.js';
import { isParentBindingConstraintsWithName } from '../calculations/isParentBindingConstraintsWithName.js';
import { isParentBindingConstraintsWithServiceId } from '../calculations/isParentBindingConstraintsWithServiceId.js';
import { isParentBindingConstraintsWithTag } from '../calculations/isParentBindingConstraintsWithTag.js';
import { isResolvedValueMetadataInjectOptions } from '../calculations/isResolvedValueMetadataInjectOptions.js';
export class BindInFluentSyntaxImplementation {
#binding;
constructor(binding) {
this.#binding = binding;
}
getIdentifier() {
return buildBindingIdentifier(this.#binding);
}
inRequestScope() {
this.#binding.scope = bindingScopeValues.Request;
return new BindWhenOnFluentSyntaxImplementation(this.#binding);
}
inSingletonScope() {
this.#binding.scope = bindingScopeValues.Singleton;
return new BindWhenOnFluentSyntaxImplementation(this.#binding);
}
inTransientScope() {
this.#binding.scope = bindingScopeValues.Transient;
return new BindWhenOnFluentSyntaxImplementation(this.#binding);
}
}
export class BindToFluentSyntaxImplementation {
#callback;
#containerModuleId;
#defaultScope;
#serviceIdentifier;
constructor(callback, containerModuleId, defaultScope, serviceIdentifier) {
this.#callback = callback;
this.#containerModuleId = containerModuleId;
this.#defaultScope = defaultScope;
this.#serviceIdentifier = serviceIdentifier;
}
to(type) {
const classMetadata = getClassMetadata(type);
const binding = {
cache: {
isRight: false,
value: undefined,
},
id: getBindingId(),
implementationType: type,
isSatisfiedBy: BindingConstraintUtils.always,
moduleId: this.#containerModuleId,
onActivation: undefined,
onDeactivation: undefined,
scope: classMetadata.scope ?? this.#defaultScope,
serviceIdentifier: this.#serviceIdentifier,
type: bindingTypeValues.Instance,
};
this.#callback(binding);
return new BindInWhenOnFluentSyntaxImplementation(binding);
}
toSelf() {
if (typeof this.#serviceIdentifier !== 'function') {
throw new Error('"toSelf" function can only be applied when a newable function is used as service identifier');
}
return this.to(this.#serviceIdentifier);
}
toConstantValue(value) {
const binding = {
cache: {
isRight: false,
value: undefined,
},
id: getBindingId(),
isSatisfiedBy: BindingConstraintUtils.always,
moduleId: this.#containerModuleId,
onActivation: undefined,
onDeactivation: undefined,
scope: bindingScopeValues.Singleton,
serviceIdentifier: this.#serviceIdentifier,
type: bindingTypeValues.ConstantValue,
value,
};
this.#callback(binding);
return new BindWhenOnFluentSyntaxImplementation(binding);
}
toDynamicValue(builder) {
const binding = {
cache: {
isRight: false,
value: undefined,
},
id: getBindingId(),
isSatisfiedBy: BindingConstraintUtils.always,
moduleId: this.#containerModuleId,
onActivation: undefined,
onDeactivation: undefined,
scope: this.#defaultScope,
serviceIdentifier: this.#serviceIdentifier,
type: bindingTypeValues.DynamicValue,
value: builder,
};
this.#callback(binding);
return new BindInWhenOnFluentSyntaxImplementation(binding);
}
toResolvedValue(factory, injectOptions) {
const binding = {
cache: {
isRight: false,
value: undefined,
},
factory,
id: getBindingId(),
isSatisfiedBy: BindingConstraintUtils.always,
metadata: this.#buildResolvedValueMetadata(injectOptions),
moduleId: this.#containerModuleId,
onActivation: undefined,
onDeactivation: undefined,
scope: this.#defaultScope,
serviceIdentifier: this.#serviceIdentifier,
type: bindingTypeValues.ResolvedValue,
};
this.#callback(binding);
return new BindInWhenOnFluentSyntaxImplementation(binding);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
toFactory(builder) {
const binding = {
cache: {
isRight: false,
value: undefined,
},
factory: builder,
id: getBindingId(),
isSatisfiedBy: BindingConstraintUtils.always,
moduleId: this.#containerModuleId,
onActivation: undefined,
onDeactivation: undefined,
scope: bindingScopeValues.Singleton,
serviceIdentifier: this.#serviceIdentifier,
type: bindingTypeValues.Factory,
};
this.#callback(binding);
return new BindWhenOnFluentSyntaxImplementation(binding);
}
toService(service) {
const binding = {
id: getBindingId(),
isSatisfiedBy: BindingConstraintUtils.always,
moduleId: this.#containerModuleId,
serviceIdentifier: this.#serviceIdentifier,
targetServiceIdentifier: service,
type: bindingTypeValues.ServiceRedirection,
};
this.#callback(binding);
}
#buildResolvedValueMetadata(options) {
const resolvedValueMetadata = {
arguments: (options ?? []).map((injectOption) => {
if (isResolvedValueMetadataInjectOptions(injectOption)) {
if (isMultipleResolvedValueMetadataInjectOptions(injectOption)) {
return {
chained: injectOption.chained ?? false,
kind: ResolvedValueElementMetadataKind.multipleInjection,
name: injectOption.name,
optional: injectOption.optional ?? false,
tags: new Map((injectOption.tags ?? []).map((tag) => [
tag.key,
tag.value,
])),
value: injectOption.serviceIdentifier,
};
}
else {
return {
kind: ResolvedValueElementMetadataKind.singleInjection,
name: injectOption.name,
optional: injectOption.optional ?? false,
tags: new Map((injectOption.tags ?? []).map((tag) => [
tag.key,
tag.value,
])),
value: injectOption.serviceIdentifier,
};
}
}
else {
return {
kind: ResolvedValueElementMetadataKind.singleInjection,
name: undefined,
optional: false,
tags: new Map(),
value: injectOption,
};
}
}),
};
return resolvedValueMetadata;
}
}
export class BindOnFluentSyntaxImplementation {
#binding;
constructor(binding) {
this.#binding = binding;
}
getIdentifier() {
return buildBindingIdentifier(this.#binding);
}
onActivation(activation) {
this.#binding.onActivation = activation;
return new BindWhenFluentSyntaxImplementation(this.#binding);
}
onDeactivation(deactivation) {
this.#binding.onDeactivation = deactivation;
if (this.#binding.scope !== bindingScopeValues.Singleton) {
throw new InversifyContainerError(InversifyContainerErrorKind.invalidOperation, `Binding for service "${stringifyServiceIdentifier(this.#binding.serviceIdentifier)}" has a deactivation function, but its scope is not singleton. Deactivation functions can only be used with singleton bindings.`);
}
return new BindWhenFluentSyntaxImplementation(this.#binding);
}
}
export class BindWhenFluentSyntaxImplementation {
#binding;
constructor(binding) {
this.#binding = binding;
}
getIdentifier() {
return buildBindingIdentifier(this.#binding);
}
when(constraint) {
this.#binding.isSatisfiedBy = constraint;
return new BindOnFluentSyntaxImplementation(this.#binding);
}
whenAnyAncestor(constraint) {
return this.when(isAnyAncestorBindingConstraints(constraint));
}
whenAnyAncestorIs(serviceIdentifier) {
return this.when(isAnyAncestorBindingConstraintsWithServiceId(serviceIdentifier));
}
whenAnyAncestorNamed(name) {
return this.when(isAnyAncestorBindingConstraintsWithName(name));
}
whenAnyAncestorTagged(tag, tagValue) {
return this.when(isAnyAncestorBindingConstraintsWithTag(tag, tagValue));
}
whenDefault() {
return this.when(isBindingConstraintsWithNoNameNorTags);
}
whenNamed(name) {
return this.when(isBindingConstraintsWithName(name));
}
whenNoParent(constraint) {
return this.when(isNotParentBindingConstraints(constraint));
}
whenNoParentIs(serviceIdentifier) {
return this.when(isNotParentBindingConstraintsWithServiceId(serviceIdentifier));
}
whenNoParentNamed(name) {
return this.when(isNotParentBindingConstraintsWithName(name));
}
whenNoParentTagged(tag, tagValue) {
return this.when(isNotParentBindingConstraintsWithTag(tag, tagValue));
}
whenParent(constraint) {
return this.when(isParentBindingConstraints(constraint));
}
whenParentIs(serviceIdentifier) {
return this.when(isParentBindingConstraintsWithServiceId(serviceIdentifier));
}
whenParentNamed(name) {
return this.when(isParentBindingConstraintsWithName(name));
}
whenParentTagged(tag, tagValue) {
return this.when(isParentBindingConstraintsWithTag(tag, tagValue));
}
whenTagged(tag, tagValue) {
return this.when(isBindingConstraintsWithTag(tag, tagValue));
}
whenNoAncestor(constraint) {
return this.when(isNoAncestorBindingConstraints(constraint));
}
whenNoAncestorIs(serviceIdentifier) {
return this.when(isNoAncestorBindingConstraintsWithServiceId(serviceIdentifier));
}
whenNoAncestorNamed(name) {
return this.when(isNoAncestorBindingConstraintsWithName(name));
}
whenNoAncestorTagged(tag, tagValue) {
return this.when(isNoAncestorBindingConstraintsWithTag(tag, tagValue));
}
}
export class BindWhenOnFluentSyntaxImplementation extends BindWhenFluentSyntaxImplementation {
#bindOnFluentSyntax;
constructor(binding) {
super(binding);
this.#bindOnFluentSyntax = new BindOnFluentSyntaxImplementation(binding);
}
onActivation(activation) {
return this.#bindOnFluentSyntax.onActivation(activation);
}
onDeactivation(deactivation) {
return this.#bindOnFluentSyntax.onDeactivation(deactivation);
}
}
export class BindInWhenOnFluentSyntaxImplementation extends BindWhenOnFluentSyntaxImplementation {
#bindInFluentSyntax;
constructor(binding) {
super(binding);
this.#bindInFluentSyntax = new BindInFluentSyntaxImplementation(binding);
}
inRequestScope() {
return this.#bindInFluentSyntax.inRequestScope();
}
inSingletonScope() {
return this.#bindInFluentSyntax.inSingletonScope();
}
inTransientScope() {
return this.#bindInFluentSyntax.inTransientScope();
}
}
//# sourceMappingURL=BindingFluentSyntaxImplementation.js.map