UNPKG

@inversifyjs/container

Version:

InversifyJs container

175 lines 8.38 kB
"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