rage-framework
Version:
## How to Install *server-side* ```bash npm install @rage-framework/server ```
222 lines • 8.81 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ContainerInstance = void 0;
const Container_1 = require("./Container");
const MissingProvidedServiceTypeError_1 = require("./error/MissingProvidedServiceTypeError");
const ServiceNotFoundError_1 = require("./error/ServiceNotFoundError");
const Token_1 = require("./Token");
const constructor_watcher_service_1 = require("../services/utils/constructor-watcher.service");
class ContainerInstance {
// -------------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------------
constructor(id) {
// -------------------------------------------------------------------------
// Private Properties
// -------------------------------------------------------------------------
this.services = new Map();
this.id = id;
}
has(identifier) {
return !!this.findService(identifier);
}
get(identifier) {
const globalContainer = Container_1.Container.of(undefined);
const service = globalContainer.findService(identifier);
const scopedService = this.findService(identifier);
if (service && service.global === true) {
return this.getServiceValue(identifier, service);
}
if (scopedService) {
return this.getServiceValue(identifier, scopedService);
}
if (service && this !== globalContainer) {
const clonedService = Object.assign({}, service);
clonedService.value = undefined;
const value = this.getServiceValue(identifier, clonedService);
this.set(identifier, value);
return value;
}
return this.getServiceValue(identifier, service);
}
getMany(id) {
return this.filterServices(id).map((service) => this.getServiceValue(id, service));
}
set(identifierOrServiceMetadata, value) {
if (identifierOrServiceMetadata instanceof Array) {
identifierOrServiceMetadata.forEach((v) => this.set(v));
return this;
}
if (typeof identifierOrServiceMetadata === 'string' ||
identifierOrServiceMetadata instanceof Token_1.Token) {
return this.set({ id: identifierOrServiceMetadata, value: value });
}
if (typeof identifierOrServiceMetadata === 'object' &&
identifierOrServiceMetadata.service) {
return this.set({
id: identifierOrServiceMetadata.service,
value: value,
});
}
if (identifierOrServiceMetadata instanceof Function) {
return this.set({
type: identifierOrServiceMetadata,
id: identifierOrServiceMetadata,
value: value,
});
}
// const newService: ServiceMetadata<any, any> = arguments.length === 1 && typeof identifierOrServiceMetadata === 'object' && !(identifierOrServiceMetadata instanceof Token) ? identifierOrServiceMetadata : undefined;
const newService = identifierOrServiceMetadata;
const service = this.services.get(newService);
if (service && service.multiple !== true) {
Object.assign(service, newService);
}
else {
this.services.set(newService, newService);
}
return this;
}
remove(...ids) {
ids.forEach((id) => {
this.filterServices(id).forEach((service) => {
this.services.delete(service);
});
});
return this;
}
reset() {
this.services.clear();
return this;
}
// -------------------------------------------------------------------------
// Private Methods
// -------------------------------------------------------------------------
filterServices(identifier) {
return Array.from(this.services.values()).filter((service) => {
if (service.id) {
return service.id === identifier;
}
if (service.type && identifier instanceof Function) {
return (service.type === identifier ||
identifier.prototype instanceof service.type);
}
return false;
});
}
findService(identifier) {
return Array.from(this.services.values()).find((service) => {
if (service.id) {
if (identifier instanceof Object &&
service.id instanceof Token_1.Token &&
identifier.service instanceof Token_1.Token) {
return service.id === identifier.service;
}
return service.id === identifier;
}
if (service.type && identifier instanceof Function) {
return service.type === identifier; // todo: not sure why it was here || identifier.prototype instanceof service.type;
}
return false;
});
}
getServiceValue(identifier, service) {
if (service && service.value !== undefined) {
return service.value;
}
if ((!service || !service.type) &&
(!service || !service.factory) &&
(typeof identifier === 'string' || identifier instanceof Token_1.Token)) {
throw new ServiceNotFoundError_1.ServiceNotFoundError(identifier);
}
let type = undefined;
if (service && service.type) {
type = service.type;
}
else if (service && service.id instanceof Function) {
type = service.id;
}
else if (identifier instanceof Function) {
type = identifier;
}
if (!service) {
if (!type) {
throw new MissingProvidedServiceTypeError_1.MissingProvidedServiceTypeError(identifier);
}
service = { type: type };
this.services.set(service, service);
}
const paramTypes = type && Reflect && Reflect.getMetadata
? Reflect.getMetadata('design:paramtypes', type)
: undefined;
let params = paramTypes
? this.initializeParams(type, paramTypes)
: [];
let value;
if (service.factory) {
params = params.filter((param) => param !== undefined);
if (service.factory instanceof Array) {
value = this.get(service.factory[0])[service.factory[1]](...params);
}
else {
value = service.factory(...params, this);
}
}
else {
if (!type) {
throw new MissingProvidedServiceTypeError_1.MissingProvidedServiceTypeError(identifier);
}
params.unshift(null);
params.push(this);
if (type.prototype.OnBefore) {
type.prototype.OnBefore.bind(type)();
}
value = new (type.bind.apply(type, params))();
constructor_watcher_service_1.constructorWatcherService.createConstructor(type['name'], {
type,
value,
});
if (value.onInit) {
value.onInit.bind(value)();
}
}
if (service && !service.transient && value) {
service.value = value;
}
if (type) {
this.applyPropertyHandlers(type, value);
}
return value;
}
initializeParams(type, paramTypes) {
return paramTypes.map((paramType, index) => {
const paramHandler = Array.from(Container_1.Container.handlers.values()).find((handler) => handler.object === type && handler.index === index);
if (paramHandler) {
return paramHandler.value(this);
}
if (paramType &&
paramType.name &&
!this.isTypePrimitive(paramType.name)) {
return this.get(paramType);
}
return undefined;
});
}
isTypePrimitive(param) {
return (['string', 'boolean', 'number', 'object'].indexOf(param.toLowerCase()) !==
-1);
}
applyPropertyHandlers(target, instance) {
Container_1.Container.handlers.forEach((handler) => {
if (typeof handler.index === 'number') {
return;
}
if (handler.object.constructor !== target &&
!(target.prototype instanceof handler.object.constructor)) {
return;
}
instance[handler.propertyName] = handler.value(this);
});
}
}
exports.ContainerInstance = ContainerInstance;
//# sourceMappingURL=ContainerInstance.js.map