UNPKG

16.1 kBSource Map (JSON)View Raw
1{"version":3,"sources":["sequelizeimp/dynamic-schema.ts"],"names":[],"mappings":"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","file":"sequelizeimp/dynamic-schema.js","sourcesContent":["import Mongoose = require('mongoose');\nimport * as Sequelize from \"sequelize\";\n//import aa = require('mongoose');\nimport * as Enumerable from 'linq';\nimport * as Types from './datatype';\nimport { Strict } from './enums/entity-strict';\nimport { Decorators } from '../core/constants/decorators';\nimport { MetadataConstants } from '../core/constants';\n\nimport { DecoratorType } from '../core/enums/decorator-type';\nimport { MetaUtils } from \"../core/metadata/utils\";\nimport { MetaData } from '../core/metadata/metadata';\nimport { IEntityParams } from './decorators/interfaces/entity-params';\nimport { sequelizeService } from './sequelizeService';\n\nexport class DynamicSchema {\n parsedSchema: any;\n schemaName: string;\n private target: Object;\n private _tablespecs: any;\n private _schema: any;\n private _relations: any = {};\n private _defaultPrimaryKey = null;\n private _removeColumnProperties = ['name','otherProperties'];\n\n constructor(target: Object, name: string, tableSpecs: any) {\n this.target = target;\n this.schemaName = name;\n this.parsedSchema = this.parse(target);\n this._tablespecs = tableSpecs;\n this._schema = sequelizeService.addScheam(this.schemaName, this.parsedSchema, this._tablespecs);\n if(this._defaultPrimaryKey){\n this._schema.beforeCreate((user, _ ) => {\n let id = this['_defaultPrimaryKey'](user);\n user[this._schema.primaryKeyField] =id;\n return user;\n });\n }\n }\n\n public getSchema() {\n return this._schema;\n }\n\n public getRelations() {\n return this._relations;\n }\n\n public getTarget() {\n return this.target;\n }\n\n private parse(target: Object) {\n if (!target || !(target instanceof Object)) {\n throw TypeError;\n }\n var schema = {};\n var primaryKeyProp;\n //var metaDataMap = this.getAllMetadataForSchema(target);\n var metaDataMap = MetaUtils.getMetaData(this.target, Decorators.COLUMN);\n for (var field in metaDataMap) {\n var fieldMetadata: MetaData = <MetaData>metaDataMap[field];\n let newParam = {}\n Object.keys(fieldMetadata.params).forEach(x => {\n if(this._removeColumnProperties.indexOf(x)<0){\n newParam[x] = fieldMetadata.params[x]\n }\n else if(x == 'otherProperties'){\n Object.keys(fieldMetadata.params[x]).forEach(subProp=>{\n newParam[subProp] = fieldMetadata.params[x][subProp];\n });\n }\n })\n if(fieldMetadata.params.primaryKey && typeof fieldMetadata.params.defaultValue==\"function\"){\n this._defaultPrimaryKey = fieldMetadata.params.defaultValue;\n delete newParam['defaultValue'];\n }\n schema[fieldMetadata.params.name] = newParam;\n }\n\n var metaDataMap1 = MetaUtils.getMetaData(this.target, Decorators.ONETOMANY);\n var oneTomanyrels = [];\n for (var field in metaDataMap1) {\n var fieldMetadata: MetaData = <MetaData>metaDataMap1[field];\n\n var params = fieldMetadata.params;\n params.propertyKey = fieldMetadata.propertyKey;\n if (!params.foreignKey)\n throw 'Please add foreign key for association ' + this.schemaName + ' -> ' + params.propertyKey;\n oneTomanyrels.push(params);\n }\n this._relations[Decorators.ONETOMANY] = oneTomanyrels;\n\n var metaDataMap2 = MetaUtils.getMetaData(this.target, Decorators.MANYTOONE);\n var manytoonerels = [];\n for (var field in metaDataMap2) {\n var fieldMetadata: MetaData = <MetaData>metaDataMap2[field];\n\n var params = fieldMetadata.params;\n params.propertyKey = fieldMetadata.propertyKey;\n if (!params.foreignKey)\n throw 'Please add foreign key for association ' + this.schemaName + ' -> ' + params.propertyKey;\n else if (!schema[params.foreignKey])\n throw 'Please choose a valid foreign key from the defined properties for ' + this.schemaName + ' -> ' + params.propertyKey;\n manytoonerels.push(params);\n }\n this._relations[Decorators.MANYTOONE] = manytoonerels;\n\n var metaDataMap3 = MetaUtils.getMetaData(this.target, Decorators.ONETOONE);\n var onetoonerels = [];\n for (var field in metaDataMap3) {\n var fieldMetadata: MetaData = <MetaData>metaDataMap3[field];\n\n var params = fieldMetadata.params;\n params.propertyKey = fieldMetadata.propertyKey;\n if (!params.foreignKey)\n throw 'Please add foreign key for association ' + this.schemaName + ' -> ' + params.propertyKey;\n onetoonerels.push(params);\n }\n this._relations[Decorators.ONETOONE] = onetoonerels;\n\n return schema;\n }\n\n private getSearchSchemaTypeForParam(fieldMetadata: MetaData): any {\n var schemaType = this.getSchemaTypeForType(fieldMetadata.getType());\n if (fieldMetadata.params && fieldMetadata.params.rel) {\n return fieldMetadata.propertyType.isArray ? [schemaType] : schemaType;\n }\n else {\n return fieldMetadata.propertyType.isArray ? [schemaType] : { type: schemaType, es_indexed: true };\n }\n //var schemaType = this.getSchemaTypeForType(paramType);\n //if (paramType.rel) {\n // //var metaData = Utils.getPrimaryKeyMetadata(paramType.itemType);\n // //var relSchema;\n // //if ((<any>fieldMetadata.params).embedded) {\n // // schema[field] = paramType.isArray ? [Types.Mixed] : Mongoose.Schema.Types.Mixed;\n // //} else {\n // // relSchema = { ref: paramType.rel, type: Mongoose.Schema.Types.ObjectId };\n // // schema[field] = paramType.isArray ? [relSchema] : relSchema;\n // //}\n\n // // need to handle embedding vs foreign key refs\n // return paramType.isArray ? [schemaType] : schemaType;\n //}\n //return paramType.isArray ? [schemaType] : {type : schemaType, es_indexed : true};\n }\n\n private getSchemaTypeForParam(fieldMetadata: MetaData) {\n var schemaType = this.getSchemaTypeForType(fieldMetadata.getType());\n return fieldMetadata.propertyType.isArray ? [schemaType] : schemaType;\n //var schemaType = this.getSchemaTypeForType(paramType.itemType);\n //if (paramType.rel) {\n // //var metaData = Utils.getPrimaryKeyMetadata(paramType.itemType);\n // //var relSchema;\n // //if ((<any>fieldMetadata.params).embedded) {\n // // schema[field] = paramType.isArray ? [Types.Mixed] : Mongoose.Schema.Types.Mixed;\n // //} else {\n // // relSchema = { ref: paramType.rel, type: Mongoose.Schema.Types.ObjectId };\n // // schema[field] = paramType.isArray ? [relSchema] : relSchema;\n // //}\n\n // // need to handle embedding vs foreign key refs\n // return paramType.isArray ? [schemaType] : schemaType;\n //}\n //return paramType.isArray ? [schemaType] : schemaType;\n }\n\n private getSchemaTypeForType(type?): any {\n switch (type) {\n case Mongoose.Types.ObjectId: return Mongoose.Schema.Types.ObjectId;\n case String: return Sequelize.STRING(128);\n case Number: return Number;\n case Buffer: return Buffer;\n case Date: return Date;\n case Boolean: return Boolean;\n case Array: return Array;\n //case undefined: return Mongoose.Schema.Types.Mixed;\n // any or no types\n case Object:\n default: return Mongoose.Schema.Types.Mixed;\n }\n }\n\n private getMongooseOptions(target: Object) {\n var meta = MetaUtils.getMetaData(<any>target, Decorators.ENTITY);\n var entityMeta = meta[0];\n var options = <any>{};\n var params = <IEntityParams>(entityMeta.params || <any>{});\n options.strict = true;\n return options;\n }\n\n private isSchemaDecorator(decorator: string) {\n return decorator === Decorators.FIELD || decorator === Decorators.ONETOMANY || decorator === Decorators.MANYTOONE || decorator === Decorators.MANYTOMANY || decorator === Decorators.ONETOONE;\n }\n\n private getAllMetadataForSchema(target: Object): { [key: string]: MetaData } {\n var metaDataMap: Array<MetaData> = MetaUtils.getMetaData(<any>target);\n var metaDataMapFiltered: { [key: string]: MetaData } = <any>{};\n for (var i in metaDataMap) {\n var meta: MetaData = metaDataMap[i] as MetaData;\n\n if (!this.isSchemaDecorator(meta.decorator))\n continue;\n\n if (metaDataMapFiltered[meta.propertyKey])\n throw \"A property cannot have more than one schema decorator\";\n\n metaDataMapFiltered[meta.propertyKey] = meta;\n }\n return metaDataMapFiltered;\n }\n}"],"sourceRoot":"/source/"}
\No newline at end of file