lambdaorm-base
Version:
472 lines • 20 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SchemaExtender = void 0;
const domain_1 = require("../../domain");
const typ3s_1 = require("typ3s");
class SchemaExtender {
// eslint-disable-next-line no-useless-constructor
constructor(exp, helper) {
this.exp = exp;
this.helper = helper;
}
extend(schema) {
this.extendEnums(schema);
this.extendEntities(schema);
this.complete(schema);
this.extendMappings(schema);
this.extendDataSources(schema);
this.extendDataStages(schema);
// views
if (schema.infrastructure && (!schema.infrastructure.views || !schema.infrastructure.views.length || schema.infrastructure.views.length === 0)) {
schema.infrastructure.views = [{ name: 'default', entities: [] }];
}
// exclude entities not used in mapping
if (schema.infrastructure && schema.infrastructure.mappings) {
for (let i = 0, length = schema.infrastructure.mappings.length; i < length; i++) {
schema.infrastructure.mappings[i] = this.clearMapping2(schema, schema.infrastructure.mappings[i]);
}
}
}
extendEnums(schema) {
if (schema.domain.enums === undefined) {
schema.domain.enums = [];
}
if (Array.isArray(schema.domain.enums)) {
for (const _enum of schema.domain.enums) {
if (_enum && _enum.extends) {
this.extendEnum(_enum, schema.domain.enums);
}
}
schema.domain.enums = this.clearEnums(schema.domain.enums);
}
}
extendEntities(schema) {
if (schema.domain.entities === undefined) {
schema.domain.entities = [];
}
for (const entity of schema.domain.entities) {
this.entitySecureArrays(entity);
}
for (const entity of schema.domain.entities) {
if (entity && entity.extends) {
this.extendEntity(entity, schema.domain.entities);
}
}
schema.domain.entities = this.clearEntities(schema.domain.entities);
}
entitySecureArrays(entity) {
if (entity.uniqueKey === undefined) {
entity.uniqueKey = [];
}
if (entity.primaryKey === undefined) {
entity.primaryKey = [];
}
if (entity.required === undefined) {
entity.required = [];
}
if (entity.indexes === undefined) {
entity.indexes = [];
}
if (entity.properties === undefined) {
entity.properties = [];
}
if (entity.relations === undefined) {
entity.relations = [];
}
if (entity.dependents === undefined) {
entity.dependents = [];
}
if (entity.constraints === undefined) {
entity.constraints = [];
}
}
extendMappings(schema) {
if (!schema.infrastructure) {
return;
}
if (!schema.infrastructure.mappings || !schema.infrastructure.mappings.length || schema.infrastructure.mappings.length === 0) {
if (schema.infrastructure.sources && schema.infrastructure.sources.length === 1 && schema.infrastructure.sources[0].name) {
if (!schema.infrastructure.sources[0].mapping) {
schema.infrastructure.sources[0].mapping = schema.infrastructure.sources[0].name;
}
schema.infrastructure.mappings = [{ name: schema.infrastructure.sources[0].mapping, entities: [] }];
}
else {
schema.infrastructure.mappings = [{ name: 'default', entities: [] }];
}
}
else {
// extend entities into mapping
for (const mapping of schema.infrastructure.mappings) {
if (mapping.entities === undefined) {
mapping.entities = [];
}
for (const entity of mapping.entities) {
this.extendEntityMapping(entity, mapping.entities);
}
}
// extends mappings
for (const mapping of schema.infrastructure.mappings) {
this.extendMapping(mapping, schema.infrastructure.mappings);
}
}
// extend mapping for model
for (let i = 0, length = schema.infrastructure.mappings.length; i < length; i++) {
schema.infrastructure.mappings[i].entities = this.helper.obj.extends(schema.infrastructure.mappings[i].entities, schema.domain.entities);
schema.infrastructure.mappings[i] = this.clearMapping(schema.infrastructure.mappings[i]);
const mapping = schema.infrastructure.mappings[i];
if (mapping && mapping.entities) {
this.completeMapping(schema.infrastructure.mappings[i]);
}
}
}
extendDataSources(schema) {
if (!schema.infrastructure || !schema.infrastructure.mappings) {
return;
}
if (!schema.infrastructure.sources || !schema.infrastructure.sources.length || schema.infrastructure.sources.length === 0) {
this.helper.logger.log('sources not defined');
schema.infrastructure.sources = [{ name: 'default', dialect: domain_1.DIALECT_DEFAULT, mapping: schema.infrastructure.mappings[0].name, connection: null }];
}
for (const source of schema.infrastructure.sources) {
if (source.mapping === undefined) {
source.mapping = schema.infrastructure.mappings[0].name;
}
}
}
extendDataStages(schema) {
if (!schema.infrastructure || !schema.infrastructure.mappings || !schema.infrastructure.sources) {
return;
}
if (!schema.infrastructure.stages || !schema.infrastructure.stages.length || schema.infrastructure.stages.length === 0) {
schema.infrastructure.stages = [{ name: 'default', sources: [{ name: schema.infrastructure.sources[0].name }] }];
}
for (const stage of schema.infrastructure.stages) {
if (stage.sources === undefined) {
stage.sources = [{ name: schema.infrastructure.sources[0].name }];
}
}
}
complete(schema) {
if (schema) {
if (schema.domain.enums) {
this.completeEnums(schema.domain.enums);
}
if (schema.domain.entities) {
if (schema.infrastructure && schema.infrastructure.views) {
this.completeEntities(schema.domain.entities, schema.infrastructure.views);
}
if (schema.domain.entities && schema.domain.entities.length) {
this.completeRelations(schema.domain.entities);
this.completeDependents(schema.domain.entities);
}
}
}
}
isCompound(parent, child) {
const parentRoot = parent.split('.')[0];
const childRoot = child.split('.')[0];
return parentRoot === childRoot;
}
clearEnums(source) {
const target = [];
if (source && source.length) {
for (const sourceEnum of source) {
if (sourceEnum.abstract === true)
continue;
target.push(sourceEnum);
}
}
return target;
}
clearEntities(source) {
const target = [];
if (source && source.length) {
for (const sourceEntity of source) {
if (sourceEntity.abstract === true)
continue;
target.push(sourceEntity);
}
}
return target;
}
completeEnums(enums) {
if (enums && enums.length) {
for (const _enum of enums) {
if (_enum.values === undefined || _enum.values === null) {
_enum.values = [];
}
else {
for (const value of _enum.values) {
if (value.value === undefined) {
value.value = value.name;
}
}
}
}
}
}
completeEntities(entities, views) {
if (entities && entities.length) {
for (const entity of entities) {
this.completeEntity(entity, views);
}
}
}
completeEntity(entity, views) {
this.entitySecureArrays(entity);
entity.composite = entity.name.includes('.');
this.completeEntityProperties(entity);
this.completeEntityRelations(entity);
if (entity.properties) {
entity.hadReadExps = entity.properties.some(p => p.readExp !== undefined);
entity.hadWriteExps = entity.properties.some(p => p.writeExp !== undefined);
entity.hadReadValues = entity.properties.some(p => p.readValue !== undefined);
entity.hadWriteValues = entity.properties.some(p => p.writeValue !== undefined);
entity.hadDefaults = entity.properties.some(p => p.default !== undefined);
entity.hadViewReadExp = views ? views.some(p => p.entities ? p.entities.some(q => q.name === entity.name && q.properties ? q.properties.some(r => r.readExp !== undefined) : false) : false) : false;
}
else {
entity.hadReadExps = false;
entity.hadWriteExps = false;
entity.hadReadValues = false;
entity.hadWriteValues = false;
entity.hadDefaults = false;
entity.hadViewReadExp = false;
}
}
completeEntityProperties(entity) {
if (entity.properties !== undefined) {
for (const property of entity.properties) {
if (property.autoIncrement) {
property.required = false;
}
else if (property.required === undefined) {
property.required = ((entity.required && entity.required.includes(property.name)) || (entity.primaryKey && entity.primaryKey.includes(property.name)) || (entity.uniqueKey && entity.uniqueKey.includes(property.name)));
}
if (property.type === undefined)
property.type = typ3s_1.Primitive.string;
if (property.type === typ3s_1.Primitive.string && property.length === undefined)
property.length = this.helper.schema.DEFAULT_LENGTH;
if (property.length !== undefined && isNaN(property.length)) {
throw new domain_1.SchemaError(`Invalid length in ${entity.name}.${property.name}`);
}
}
}
}
completeEntityRelations(entity) {
if (entity.relations !== undefined) {
for (const relation of entity.relations) {
if (relation.type === undefined)
relation.type = domain_1.RelationType.oneToMany;
// All relations manyToOne are weak
if (relation.type === domain_1.RelationType.manyToOne)
relation.weak = true;
if (relation.weak === undefined)
relation.weak = false;
}
}
}
completeRelations(entities) {
for (const source of entities) {
if (source.relations) {
for (const sourceRelation of source.relations) {
if (sourceRelation.target && (sourceRelation.type === domain_1.RelationType.oneToMany || sourceRelation.type === domain_1.RelationType.oneToOne)) {
this.completeRelation(source, sourceRelation, entities);
}
}
}
else {
source.relations = [];
}
}
}
completeRelation(source, sourceRelation, entities) {
const targetEntity = entities.find(p => p.name === sourceRelation.entity);
if (targetEntity && targetEntity.relations) {
const exists = targetEntity.relations.find(p => p.name === sourceRelation.target) !== undefined;
if (!exists) {
targetEntity.relations.push({
name: sourceRelation.target,
type: sourceRelation.type === domain_1.RelationType.oneToOne ? domain_1.RelationType.oneToOne : domain_1.RelationType.manyToOne,
composite: this.isCompound(targetEntity.name, source.name),
from: sourceRelation.to,
entity: source.name,
weak: true,
to: sourceRelation.from,
target: sourceRelation.name
});
}
}
}
completeDependents(entities) {
for (const entity of entities) {
entity.dependents = [];
for (const related of entities) {
if (!related.relations) {
continue;
}
for (const relation of related.relations) {
if (relation.entity === entity.name && !relation.weak) {
const dependent = { entity: related.name, relation };
entity.dependents.push(dependent);
}
}
}
}
}
extendEnum(_enum, enums) {
const base = enums.find(p => p.name === _enum.extends);
if (base === undefined) {
throw new domain_1.SchemaError(`${_enum.extends} not found`);
}
if (base.extends) {
this.extendEnum(base, enums);
}
// extend values
if (base.values !== undefined && base.values.length > 0) {
if (_enum.values === undefined || _enum.values === null) {
_enum.values = [];
}
_enum.values = this.helper.obj.extends(_enum.values, base.values);
}
// elimina dado que ya fue extendido
delete _enum.extends;
}
extendEntity(entity, entities) {
const base = entities.find(p => p.name === entity.extends);
if (base === undefined) {
throw new domain_1.SchemaError(`${entity.extends} not found`);
}
if (base.extends) {
this.extendEntity(base, entities);
}
if (entity.primaryKey === undefined && base.primaryKey !== undefined)
entity.primaryKey = base.primaryKey;
// extend properties
if (base.properties !== undefined && base.properties.length > 0) {
if (entity.properties === undefined) {
entity.properties = [];
}
entity.properties = this.helper.obj.extends(entity.properties, base.properties);
}
// extend relations
if (base.relations && base.relations.length > 0) {
entity.relations = this.helper.obj.extends(entity.relations, base.relations);
}
// elimina dado que ya fue extendido
delete entity.extends;
}
extendMapping(mapping, mappings) {
if (mapping && mapping.extends) {
const base = mappings.find(p => p.name === mapping.extends);
if (base === undefined) {
throw new domain_1.SchemaError(`${mapping.extends} not found`);
}
this.extendMapping(base, mappings);
mapping.entities = this.helper.obj.extends(mapping.entities, base.entities);
// elimina dado que ya fue extendido
delete mapping.extends;
}
}
extendEntityMapping(entity, entities) {
if (entity && entity.extends) {
const base = entities.find(p => p.name === entity.extends);
if (base === undefined) {
throw new domain_1.SchemaError(`${entity.extends} not found`);
}
this.extendEntityMapping(base, entities);
if (entity.uniqueKey === undefined && base.uniqueKey !== undefined) {
entity.uniqueKey = base.uniqueKey;
}
if (entity.mapping === undefined && base.mapping !== undefined) {
entity.mapping = base.mapping;
}
this.extendEntityMappingIndexes(entity, base);
this.extendEntityMappingProperties(entity, base);
// delete since it was already extended
delete entity.extends;
}
}
extendEntityMappingIndexes(entity, base) {
if (base.indexes !== undefined && base.indexes.length > 0) {
if (entity.indexes === undefined) {
entity.indexes = [];
}
entity.indexes = this.helper.obj.extends(entity.indexes, base.indexes);
}
}
extendEntityMappingProperties(entity, base) {
if (base.properties !== undefined && base.properties.length > 0) {
if (entity.properties === undefined) {
entity.properties = [];
}
entity.properties = this.helper.obj.extends(entity.properties, base.properties);
}
}
completeMapping(mapping) {
if (mapping.entities === undefined) {
return;
}
for (const entity of mapping.entities) {
if (this.helper.val.isEmpty(entity.mapping)) {
entity.mapping = entity.name;
}
if (entity.properties === undefined || entity.properties.length === 0) {
entity.hadKeys = false;
continue;
}
for (const property of entity.properties) {
if (this.helper.val.isEmpty(property.mapping)) {
property.mapping = property.name;
}
}
entity.hadKeys = entity.properties.some(p => p.key !== undefined);
}
}
clearMapping(source) {
const target = { name: source.name, mapping: source.mapping, entities: [] };
if (source && source.entities) {
for (const sourceEntity of source.entities) {
if (sourceEntity.abstract === true)
continue;
if (target.entities === undefined)
target.entities = [];
target.entities.push(sourceEntity);
}
}
return target;
}
clearMapping2(schema, source) {
const target = { name: source.name, mapping: source.mapping, entities: [] };
if (source && source.entities) {
for (const sourceEntity of source.entities) {
if (!this.existsInMapping(schema, source.name, sourceEntity.name))
continue;
if (target.entities === undefined)
target.entities = [];
target.entities.push(sourceEntity);
}
}
return target;
}
existsInMapping(schema, mapping, entity) {
if (!schema.infrastructure || !schema.infrastructure.sources || !schema.infrastructure.stages) {
return false;
}
// const context = { entity, action: ObservableAction.ddl, read: false, write: true, dml: false, ddl: true }
const info = { entity, action: domain_1.SentenceAction.undefined, category: domain_1.SentenceCategory.undefined, type: domain_1.SentenceType.dml };
const dataSourcesNames = schema.infrastructure.sources.filter(p => p.mapping === mapping).map(p => p.name);
for (const stage of schema.infrastructure.stages) {
const ruleDataSources = stage.sources.filter(p => dataSourcesNames.includes(p.name));
for (const ruleDataSource of ruleDataSources) {
if (ruleDataSource.condition === undefined || this.exp.eval(ruleDataSource.condition, info)) {
return true;
}
}
}
return false;
}
}
exports.SchemaExtender = SchemaExtender;
//# sourceMappingURL=schemaExtender.js.map