@inversifyjs/container
Version:
InversifyJs container
175 lines • 8.38 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BindingManager = void 0;
const common_1 = require("@inversifyjs/common");
const core_1 = require("@inversifyjs/core");
const isBindingIdentifier_1 = require("../../binding/calculations/isBindingIdentifier");
const BindingFluentSyntaxImplementation_1 = require("../../binding/models/BindingFluentSyntaxImplementation");
const getFirstIterableResult_1 = require("../../common/calculations/getFirstIterableResult");
const InversifyContainerError_1 = require("../../error/models/InversifyContainerError");
const InversifyContainerErrorKind_1 = require("../../error/models/InversifyContainerErrorKind");
class BindingManager {
#deactivationParams;
#defaultScope;
#planResultCacheManager;
#serviceReferenceManager;
constructor(deactivationParams, defaultScope, planResultCacheManager, serviceReferenceManager) {
this.#deactivationParams = deactivationParams;
this.#defaultScope = defaultScope;
this.#planResultCacheManager = planResultCacheManager;
this.#serviceReferenceManager = serviceReferenceManager;
}
bind(serviceIdentifier) {
return new BindingFluentSyntaxImplementation_1.BindToFluentSyntaxImplementation((binding) => {
this.#setBinding(binding);
}, undefined, this.#defaultScope, serviceIdentifier);
}
isBound(serviceIdentifier, options) {
const bindings = this.#serviceReferenceManager.bindingService.get(serviceIdentifier);
return this.#isAnyValidBinding(serviceIdentifier, bindings, options);
}
isCurrentBound(serviceIdentifier, options) {
const bindings = this.#serviceReferenceManager.bindingService.getNonParentBindings(serviceIdentifier);
return this.#isAnyValidBinding(serviceIdentifier, bindings, options);
}
async rebind(serviceIdentifier) {
await this.unbind(serviceIdentifier);
return this.bind(serviceIdentifier);
}
rebindSync(serviceIdentifier) {
this.unbindSync(serviceIdentifier);
return this.bind(serviceIdentifier);
}
async unbind(identifier) {
await this.#unbind(identifier);
}
async unbindAll() {
const nonParentBoundServiceIds = [
...this.#serviceReferenceManager.bindingService.getNonParentBoundServices(),
];
await Promise.all(nonParentBoundServiceIds.map(async (serviceId) => (0, core_1.resolveServiceDeactivations)(this.#deactivationParams, serviceId)));
/*
* Removing service related objects here so unbindAll is deterministic.
*
* Removing service related objects as soon as resolveModuleDeactivations takes
* effect leads to module deactivations not triggering previously deleted
* deactivations, introducing non determinism depending in the order in which
* services are deactivated.
*/
for (const serviceId of nonParentBoundServiceIds) {
this.#serviceReferenceManager.activationService.removeAllByServiceId(serviceId);
this.#serviceReferenceManager.bindingService.removeAllByServiceId(serviceId);
this.#serviceReferenceManager.deactivationService.removeAllByServiceId(serviceId);
}
this.#serviceReferenceManager.planResultCacheService.clearCache();
}
unbindSync(identifier) {
const result = this.#unbind(identifier);
if (result !== undefined) {
this.#throwUnexpectedAsyncUnbindOperation(identifier);
}
}
#setBinding(binding) {
this.#serviceReferenceManager.bindingService.set(binding);
this.#planResultCacheManager.invalidateService({
binding: binding,
kind: core_1.CacheBindingInvalidationKind.bindingAdded,
});
}
#throwUnexpectedAsyncUnbindOperation(identifier) {
let errorMessage;
if ((0, isBindingIdentifier_1.isBindingIdentifier)(identifier)) {
const bindingsById = this.#serviceReferenceManager.bindingService.getById(identifier.id);
const bindingServiceIdentifier = (0, getFirstIterableResult_1.getFirstIterableResult)(bindingsById)?.serviceIdentifier;
if (bindingServiceIdentifier === undefined) {
errorMessage =
'Unexpected asynchronous deactivation when unbinding binding identifier. Consider using Container.unbind() instead.';
}
else {
errorMessage = `Unexpected asynchronous deactivation when unbinding "${(0, common_1.stringifyServiceIdentifier)(bindingServiceIdentifier)}" binding. Consider using Container.unbind() instead.`;
}
}
else {
errorMessage = `Unexpected asynchronous deactivation when unbinding "${(0, common_1.stringifyServiceIdentifier)(identifier)}" service. Consider using Container.unbind() instead.`;
}
throw new InversifyContainerError_1.InversifyContainerError(InversifyContainerErrorKind_1.InversifyContainerErrorKind.invalidOperation, errorMessage);
}
#unbind(identifier) {
if ((0, isBindingIdentifier_1.isBindingIdentifier)(identifier)) {
return this.#unbindBindingIdentifier(identifier);
}
return this.#unbindServiceIdentifier(identifier);
}
#unbindBindingIdentifier(identifier) {
const bindingsIterable = this.#serviceReferenceManager.bindingService.getById(identifier.id);
const bindings = bindingsIterable === undefined ? undefined : [...bindingsIterable];
const result = (0, core_1.resolveBindingsDeactivations)(this.#deactivationParams, bindingsIterable);
if (result === undefined) {
this.#clearAfterUnbindBindingIdentifier(bindings, identifier);
}
else {
return result.then(() => {
this.#clearAfterUnbindBindingIdentifier(bindings, identifier);
});
}
}
#clearAfterUnbindBindingIdentifier(bindings, identifier) {
this.#serviceReferenceManager.bindingService.removeById(identifier.id);
if (bindings !== undefined) {
for (const binding of bindings) {
this.#planResultCacheManager.invalidateService({
binding,
kind: core_1.CacheBindingInvalidationKind.bindingRemoved,
});
}
}
}
#unbindServiceIdentifier(identifier) {
const bindingsIterable = this.#serviceReferenceManager.bindingService.get(identifier);
const bindings = bindingsIterable === undefined ? undefined : [...bindingsIterable];
const result = (0, core_1.resolveBindingsDeactivations)(this.#deactivationParams, bindingsIterable);
if (result === undefined) {
this.#clearAfterUnbindServiceIdentifier(identifier, bindings);
}
else {
return result.then(() => {
this.#clearAfterUnbindServiceIdentifier(identifier, bindings);
});
}
}
#clearAfterUnbindServiceIdentifier(identifier, bindings) {
this.#serviceReferenceManager.activationService.removeAllByServiceId(identifier);
this.#serviceReferenceManager.bindingService.removeAllByServiceId(identifier);
this.#serviceReferenceManager.deactivationService.removeAllByServiceId(identifier);
if (bindings !== undefined) {
for (const binding of bindings) {
this.#planResultCacheManager.invalidateService({
binding,
kind: core_1.CacheBindingInvalidationKind.bindingRemoved,
});
}
}
}
#isAnyValidBinding(serviceIdentifier, bindings, options) {
if (bindings === undefined) {
return false;
}
const bindingConstraints = {
getAncestor: () => undefined,
name: options?.name,
serviceIdentifier,
tags: new Map(),
};
if (options?.tag !== undefined) {
bindingConstraints.tags.set(options.tag.key, options.tag.value);
}
for (const binding of bindings) {
if (binding.isSatisfiedBy(bindingConstraints)) {
return true;
}
}
return false;
}
}
exports.BindingManager = BindingManager;
//# sourceMappingURL=BindingManager.js.map