UNPKG

miter

Version:

A typescript web framework based on ExpressJs based loosely on SailsJs

201 lines 10.2 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); require("reflect-metadata"); const injectable_decorator_1 = require("../decorators/services/injectable.decorator"); const name_decorator_1 = require("../decorators/services/name.decorator"); const orm_1 = require("../metadata/server/orm"); const model_1 = require("../metadata/orm/model"); const prop_1 = require("../metadata/orm/prop"); const has_many_1 = require("../metadata/orm/associations/has-many"); const belongs_to_1 = require("../metadata/orm/associations/belongs-to"); const has_one_1 = require("../metadata/orm/associations/has-one"); const logger_core_1 = require("../services/logger-core"); const logger_1 = require("../services/logger"); const sequelize_1 = require("./sequelize"); const orm_transform_service_1 = require("../services/orm-transform.service"); const transaction_service_1 = require("../services/transaction.service"); const db_impl_1 = require("./impl/db-impl"); let OrmReflector = class OrmReflector { constructor(logger, loggerCore, ormMeta, transactionService, ormTransform, sql) { this.logger = logger; this.loggerCore = loggerCore; this.ormMeta = ormMeta; this.transactionService = transactionService; this.ormTransform = ormTransform; this.sql = sql; this.models = new Map(); this.modelsByTableName = new Map(); this.dbImplLogger = this.loggerCore.getSubsystem('db-impl'); } init() { return __awaiter(this, void 0, void 0, function* () { this.logger.verbose(`Initializing ORM...`); yield this.sql.init(); let models = this.ormMeta.models; this.reflectModels(models); this.reflectAssociations(models); this.createDbImpls(models); yield this.sql.sync(); this.logger.info(`Finished initializing ORM.`); }); } reflectModels(models) { for (let q = 0; q < models.length; q++) { this.reflectModel(models[q]); } } reflectModel(modelFn) { if (this.models.has(modelFn)) throw new Error(`A model was passed to the orm-reflector twice: ${modelFn.name || modelFn}.`); let modelProto = modelFn.prototype; let meta = Reflect.getOwnMetadata(model_1.ModelMetadataSym, modelProto); if (!meta) throw new Error(`Expecting class with @Model decorator, could not reflect model properties for ${modelProto}.`); let modelOptions = meta; modelOptions = this.ormTransform.transformModel(modelOptions) || modelOptions; modelOptions.tableName = modelOptions.tableName || this.ormTransform.transformModelName(modelFn.name) || modelFn.name; let dupTable = this.modelsByTableName.get(modelOptions.tableName); if (dupTable) throw new Error(`Defining multiple models with the same table name! ${dupTable.name || dupTable} and ${modelFn.name || modelFn}`); this.modelsByTableName.set(modelOptions.tableName, modelFn); let columns = {}; let props = Reflect.getOwnMetadata(model_1.ModelPropertiesSym, modelProto) || []; for (let q = 0; q < props.length; q++) { let propName = props[q]; let propMeta = Reflect.getOwnMetadata(prop_1.PropMetadataSym, modelProto, propName); if (!propMeta) throw new Error(`Could not find model property metadata for property ${modelFn.name || modelFn}.${propName}.`); let columnMeta = propMeta; columnMeta = this.ormTransform.transformColumn(columnMeta) || columnMeta; columnMeta.field = columnMeta.columnName || this.ormTransform.transformColumnName(propName) || propName; columns[propName] = columnMeta; } let model = this.sql.define(modelOptions.tableName, columns, modelOptions); this.models.set(modelFn, model); } reflectAssociations(models) { for (let q = 0; q < models.length; q++) { this.reflectModelAssociations(models[q]); } } reflectModelAssociations(modelFn) { let model = this.models.get(modelFn); if (!model) throw new Error(`Could not reflect model associations for a model that failed to be reflected: ${modelFn.name || modelFn}.`); let modelProto = modelFn.prototype; let meta = Reflect.getOwnMetadata(model_1.ModelMetadataSym, modelProto); if (!meta) throw new Error(`Expecting class with @Model decorator, could not reflect model properties for ${modelProto}.`); let associationTypes = [ { sqlName: 'hasMany', msgName: 'has-many', associationsSym: has_many_1.ModelHasManyAssociationsSym, metadataSym: has_many_1.HasManyMetadataSym, transform: (propMeta, propName) => { } }, { sqlName: 'belongsTo', msgName: 'belongs-to', associationsSym: belongs_to_1.ModelBelongsToAssociationsSym, metadataSym: belongs_to_1.BelongsToMetadataSym, transform: (propMeta, propName) => { propMeta.foreignKey = propMeta.foreignKey || this.ormTransform.transformAssociationColumnName(propName) || propName; } }, { sqlName: 'hasOne', msgName: 'has-one', associationsSym: has_one_1.ModelHasOneAssociationsSym, metadataSym: has_one_1.HasOneMetadataSym, transform: (propMeta, propName) => { } } ]; for (let q = 0; q < associationTypes.length; q++) { let def = associationTypes[q]; let associationNames = Reflect.getOwnMetadata(def.associationsSym, modelProto) || []; for (let w = 0; w < associationNames.length; w++) { let propName = associationNames[w]; let propMeta = Reflect.getOwnMetadata(def.metadataSym, modelProto, propName); if (!propMeta) throw new Error(`Could not find model ${def.msgName} metadata for property ${modelFn.name || modelFn}.${propName}`); let foreignModelFn = this.resolveForeignModelFn(propMeta); if (!foreignModelFn) throw new Error(`Could not resolve foreign model for ${def.msgName} association ${modelFn.name || modelFn}.${propName}`); let foreignModel = this.models.get(foreignModelFn); if (!foreignModel) throw new Error(`Could not create ${def.msgName} association ${modelFn.name || modelFn}.${propName} to model that has not been reflected: ${foreignModelFn.name || foreignModelFn}`); let sqlMeta = propMeta; sqlMeta = this.ormTransform.transformAssociation(sqlMeta) || sqlMeta; if (def.transform) def.transform(sqlMeta, propName); model[def.sqlName](foreignModel, propMeta); } } } createDbImpls(models) { for (let q = 0; q < models.length; q++) { let modelFn = models[q]; let model = this.models.get(modelFn); if (!model) throw new Error(`Could not reflect model associations for a model that failed to be reflected: ${modelFn.name || modelFn}.`); let db = new db_impl_1.DbImpl(modelFn, model, this.sql, this.dbImplLogger, this.transactionService); modelFn.db = db; } } isStaticModelT(test) { return test && !!test.db; } isTableNameRef(test) { return test.tableName; } isModelNameRef(test) { return test.modelName; } resolveForeignModelFn(meta) { let fmod = meta.foreignModel; if (!fmod) return undefined; if (this.isStaticModelT(fmod)) return fmod; if (typeof fmod === 'function') return meta.foreignModel = fmod(); else if (this.isTableNameRef(fmod)) return meta.foreignModel = this.modelsByTableName.get(fmod.tableName); else if (this.isModelNameRef(fmod)) { let modelName = fmod.modelName; return meta.foreignModel = [...this.models.keys()].find(model => model.name == modelName); } } }; OrmReflector = __decorate([ injectable_decorator_1.Injectable(), name_decorator_1.Name('orm'), __metadata("design:paramtypes", [logger_1.Logger, logger_core_1.LoggerCore, orm_1.OrmMetadata, transaction_service_1.TransactionService, orm_transform_service_1.OrmTransformService, sequelize_1.Sequelize]) ], OrmReflector); exports.OrmReflector = OrmReflector; //# sourceMappingURL=reflector.js.map