@expressots/core
Version:
Expressots - modern, fast, lightweight nodejs web framework (@core)
187 lines (186 loc) • 9.06 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.plan = plan;
exports.createMockRequest = createMockRequest;
exports.getBindingDictionary = getBindingDictionary;
const binding_count_1 = require("../bindings/binding_count");
const ERROR_MSGS = __importStar(require("../constants/error_msgs"));
const literal_types_1 = require("../constants/literal_types");
const METADATA_KEY = __importStar(require("../constants/metadata_keys"));
const exceptions_1 = require("../utils/exceptions");
const serialization_1 = require("../utils/serialization");
const context_1 = require("./context");
const metadata_1 = require("./metadata");
const plan_1 = require("./plan");
const reflection_utils_1 = require("./reflection_utils");
const request_1 = require("./request");
const target_1 = require("./target");
function getBindingDictionary(cntnr) {
return cntnr._bindingDictionary;
}
function _createTarget(isMultiInject, targetType, serviceIdentifier, name, key, value) {
const metadataKey = isMultiInject
? METADATA_KEY.MULTI_INJECT_TAG
: METADATA_KEY.INJECT_TAG;
const injectMetadata = new metadata_1.Metadata(metadataKey, serviceIdentifier);
const target = new target_1.Target(targetType, name, serviceIdentifier, injectMetadata);
if (key !== undefined) {
const tagMetadata = new metadata_1.Metadata(key, value);
target.metadata.push(tagMetadata);
}
return target;
}
function _getActiveBindings(metadataReader, avoidConstraints, context, parentRequest, target) {
let bindings = getBindings(context.container, target.serviceIdentifier);
let activeBindings = [];
// automatic binding
if (bindings.length === binding_count_1.BindingCount.NoBindingsAvailable &&
context.container.options.autoBindInjectable &&
typeof target.serviceIdentifier === "function" &&
metadataReader.getConstructorMetadata(target.serviceIdentifier)
.compilerGeneratedMetadata) {
context.container.bind(target.serviceIdentifier).toSelf();
bindings = getBindings(context.container, target.serviceIdentifier);
}
// multiple bindings available
if (!avoidConstraints) {
// apply constraints if available to reduce the number of active bindings
activeBindings = bindings.filter((binding) => {
const request = new request_1.Request(binding.serviceIdentifier, context, parentRequest, binding, target);
return binding.constraint(request);
});
}
else {
// simple injection or multi-injection without constraints
activeBindings = bindings;
}
// validate active bindings
_validateActiveBindingCount(target.serviceIdentifier, activeBindings, target, context.container);
return activeBindings;
}
function _validateActiveBindingCount(serviceIdentifier, bindings, target, container) {
switch (bindings.length) {
case binding_count_1.BindingCount.NoBindingsAvailable:
if (target.isOptional()) {
return bindings;
}
else {
const serviceIdentifierString = (0, serialization_1.getServiceIdentifierAsString)(serviceIdentifier);
let msg = ERROR_MSGS.NOT_REGISTERED;
msg += (0, serialization_1.listMetadataForTarget)(serviceIdentifierString, target);
msg += (0, serialization_1.listRegisteredBindingsForServiceIdentifier)(container, serviceIdentifierString, getBindings);
throw new Error(msg);
}
case binding_count_1.BindingCount.OnlyOneBindingAvailable:
return bindings;
case binding_count_1.BindingCount.MultipleBindingsAvailable:
default:
if (!target.isArray()) {
const serviceIdentifierString = (0, serialization_1.getServiceIdentifierAsString)(serviceIdentifier);
let msg = `${ERROR_MSGS.AMBIGUOUS_MATCH} ${serviceIdentifierString}`;
msg += (0, serialization_1.listRegisteredBindingsForServiceIdentifier)(container, serviceIdentifierString, getBindings);
throw new Error(msg);
}
else {
return bindings;
}
}
}
function _createSubRequests(metadataReader, avoidConstraints, serviceIdentifier, context, parentRequest, target) {
let activeBindings;
let childRequest;
if (parentRequest === null) {
activeBindings = _getActiveBindings(metadataReader, avoidConstraints, context, null, target);
childRequest = new request_1.Request(serviceIdentifier, context, null, activeBindings, target);
const thePlan = new plan_1.Plan(context, childRequest);
context.addPlan(thePlan);
}
else {
activeBindings = _getActiveBindings(metadataReader, avoidConstraints, context, parentRequest, target);
childRequest = parentRequest.addChildRequest(target.serviceIdentifier, activeBindings, target);
}
activeBindings.forEach((binding) => {
let subChildRequest = null;
if (target.isArray()) {
subChildRequest = childRequest.addChildRequest(binding.serviceIdentifier, binding, target);
}
else {
if (binding.cache) {
return;
}
subChildRequest = childRequest;
}
if (binding.type === literal_types_1.BindingTypeEnum.Instance &&
binding.implementationType !== null) {
const dependencies = (0, reflection_utils_1.getDependencies)(metadataReader, binding.implementationType);
if (!context.container.options.skipBaseClassChecks) {
// Throw if a derived class does not implement its constructor explicitly
// We do this to prevent errors when a base class (parent) has dependencies
// and one of the derived classes (children) has no dependencies
const baseClassDependencyCount = (0, reflection_utils_1.getBaseClassDependencyCount)(metadataReader, binding.implementationType);
if (dependencies.length < baseClassDependencyCount) {
const error = ERROR_MSGS.ARGUMENTS_LENGTH_MISMATCH((0, reflection_utils_1.getFunctionName)(binding.implementationType));
throw new Error(error);
}
}
dependencies.forEach((dependency) => {
_createSubRequests(metadataReader, false, dependency.serviceIdentifier, context, subChildRequest, dependency);
});
}
});
}
function getBindings(container, serviceIdentifier) {
let bindings = [];
const bindingDictionary = getBindingDictionary(container);
if (bindingDictionary.hasKey(serviceIdentifier)) {
bindings = bindingDictionary.get(serviceIdentifier);
}
else if (container.parent !== null) {
// recursively try to get bindings from parent container
bindings = getBindings(container.parent, serviceIdentifier);
}
return bindings;
}
function plan(metadataReader, container, isMultiInject, targetType, serviceIdentifier, key, value, avoidConstraints = false) {
const context = new context_1.Context(container);
const target = _createTarget(isMultiInject, targetType, serviceIdentifier, "", key, value);
try {
_createSubRequests(metadataReader, avoidConstraints, serviceIdentifier, context, null, target);
return context;
}
catch (error) {
if ((0, exceptions_1.isStackOverflowExeption)(error)) {
(0, serialization_1.circularDependencyToException)(context.plan.rootRequest);
}
throw error;
}
}
function createMockRequest(container, serviceIdentifier, key, value) {
const target = new target_1.Target(literal_types_1.TargetTypeEnum.Variable, "", serviceIdentifier, new metadata_1.Metadata(key, value));
const context = new context_1.Context(container);
const request = new request_1.Request(serviceIdentifier, context, null, [], target);
return request;
}
;