@allgemein/schema-api
Version:
Library for schema api
200 lines • 7.17 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MetadataRegistry = void 0;
const lodash_1 = require("lodash");
/**
* Handler for metadata
*/
const Constants_1 = require("./../Constants");
const base_1 = require("@allgemein/base");
const events_1 = require("events");
const ClassRef_1 = require("../ClassRef");
/**
* Registry for metadata of classes and there properties
*/
class MetadataRegistry extends events_1.EventEmitter {
constructor() {
super();
this.metadata = [];
this.cached = [];
this.schemas = [];
this.targets = [];
this.setMaxListeners(1000);
this.targets = [];
this.schemas = [];
this.metadata = base_1.MetadataStorage.key(Constants_1.METADATA_REGISTRY);
}
static $() {
if (!this.$self) {
this.$self = new MetadataRegistry();
}
return this.$self;
}
static reset() {
this.$self = null;
}
/**
* Add typed element to the local registry
*
* @param context
* @param options
*/
add(context, options, trigger = true) {
options.metaType = context;
// find?
const id = MetadataRegistry.INC++;
this.metadata.push(options);
if (this.targets.indexOf(options.target) === -1) {
this.targets.push(options.target);
}
if (context === Constants_1.METATYPE_SCHEMA) {
if (this.schemas.indexOf(options.name) === -1) {
this.schemas.push(options.name);
}
}
if (trigger) {
Object.defineProperty(options, Constants_1.K_TRIGGERED, { value: true });
this.notify(Constants_1.C_EVENT_ADD, context, options);
}
return options;
}
/**
* Add cached content mostly for ClassRef instances throw AbstractRef
*
* @param context
* @param options
*/
addCached(context, options) {
options.metaType = context;
this.cached.push(options);
return options;
}
notify(eventName, context, options) {
this.emit(eventName, context, options);
}
remove(context, c, trigger = true) {
const removed = (0, lodash_1.remove)(this.metadata, x => x.metaType === context && c(x));
if (!(0, lodash_1.isEmpty)(removed) && trigger) {
this.notify(Constants_1.C_EVENT_REMOVE, context, removed);
}
}
// private update(context: METADATA_TYPE) {
// this.emit(C_EVENT_UPDATE, {});
// }
getByContext(context) {
return this.metadata.filter(x => x.metaType === context);
}
getTargets() {
return this.targets;
}
/**
* Return the metadata/options for some entry (entity/property/classref/...). A copy of the original will be delivered.
*
* @param context
* @param target
* @param attributes
* @param propertyName
*/
getByContextAndTarget(context, target, attributes = null, propertyName) {
const data = (0, lodash_1.cloneDeep)(this.metadata.filter(x => x.metaType === context &&
((0, lodash_1.isFunction)(target) ? x.target === target : ClassRef_1.ClassRef.getClassName(x.target) === target) &&
(propertyName ? x.propertyName === propertyName : true)));
if (attributes && !(0, lodash_1.isEmpty)(data)) {
this.mergeAttributes(context, target, data, attributes);
}
return data;
}
mergeAttributes(context, target, data, mode = null) {
let attributes = [];
if (context === Constants_1.METATYPE_PROPERTY) {
// merge with properties
attributes = this.getAttributesForTargetProperties(context, target);
}
else {
attributes = this.getAttributesForTarget(context, target);
}
for (const attribute of attributes) {
let toExtend = null;
if (attribute.propertyName) {
toExtend = data.find((x) => x.metaType === Constants_1.METATYPE_PROPERTY && x.propertyName === attribute.propertyName);
}
else {
toExtend = data.find((x) => x.metaType === context);
}
if (toExtend) {
switch (mode) {
case 'assign':
(0, lodash_1.assign)(toExtend, attribute.attributes);
break;
case 'merge':
(0, lodash_1.merge)(toExtend, attribute.attributes);
break;
case 'defaults':
(0, lodash_1.defaults)(toExtend, attribute.attributes);
break;
}
}
}
}
getAttributesForTarget(context, target) {
return (0, lodash_1.cloneDeep)(this.metadata.filter((x) => x.targetTypes &&
!x.propertyName &&
x.attributes &&
x.targetTypes.includes(context) &&
x.target === target));
}
getAttributesForTargetProperty(context, target, propertyName) {
return (0, lodash_1.cloneDeep)(this.metadata.filter((x) => x.targetTypes &&
x.propertyName === propertyName &&
x.attributes &&
x.targetTypes.includes(context) &&
x.target === target));
}
getAttributesForTargetProperties(context, target) {
return (0, lodash_1.cloneDeep)(this.metadata.filter((x) => x.targetTypes &&
x.propertyName &&
x.attributes &&
x.targetTypes.includes(context) &&
x.target === target));
}
getByTarget(target) {
return (0, lodash_1.cloneDeep)(this.metadata.filter(x => x.target === target));
}
createSearchFunction(find) {
let lookup = find;
if (!(0, lodash_1.isFunction)(find)) {
const _keys = (0, lodash_1.keys)(find);
lookup = (x) => {
return _keys.map(k => find[k] === x[k]).reduce((previousValue, currentValue) => previousValue && currentValue);
};
}
return lookup;
}
find(context, find) {
const lookup = this.createSearchFunction(find);
return this.metadata.find((x => x.metaType === context && lookup(x)));
}
findCached(context, find) {
const lookup = this.createSearchFunction(find);
return this.cached.find((x => x.metaType === context && lookup(x)));
}
filter(context, find) {
const lookup = this.createSearchFunction(find);
return this.metadata.filter((x => x.context === context && lookup(x)));
}
getMetadata() {
return this.metadata;
}
getCached() {
return this.cached;
}
getSchemas() {
return (0, lodash_1.uniq)(this.metadata.filter((x => x.context === Constants_1.METATYPE_SCHEMA)).map(x => x.name));
}
getMetadatasForSchema(schema) {
return this.metadata.filter((x => x.context === Constants_1.METATYPE_SCHEMA && x.name === schema));
}
}
exports.MetadataRegistry = MetadataRegistry;
MetadataRegistry.INC = 0;
//# sourceMappingURL=MetadataRegistry.js.map