1 | import Mongoose = require('mongoose');
|
2 | import * as Sequelize from "sequelize";
|
3 |
|
4 | import * as Enumerable from 'linq';
|
5 | import * as Types from './datatype';
|
6 | import { Strict } from './enums/entity-strict';
|
7 | import { Decorators } from '../core/constants/decorators';
|
8 | import { MetadataConstants } from '../core/constants';
|
9 |
|
10 | import { DecoratorType } from '../core/enums/decorator-type';
|
11 | import { MetaUtils } from "../core/metadata/utils";
|
12 | import { MetaData } from '../core/metadata/metadata';
|
13 | import { IEntityParams } from './decorators/interfaces/entity-params';
|
14 | import { sequelizeService } from './sequelizeService';
|
15 |
|
16 | export class DynamicSchema {
|
17 | parsedSchema: any;
|
18 | schemaName: string;
|
19 | private target: Object;
|
20 | private _tablespecs: any;
|
21 | private _schema: any;
|
22 | private _relations: any = {};
|
23 | private _defaultPrimaryKey = null;
|
24 | private _removeColumnProperties = ['name','otherProperties'];
|
25 |
|
26 | constructor(target: Object, name: string, tableSpecs: any) {
|
27 | this.target = target;
|
28 | this.schemaName = name;
|
29 | this.parsedSchema = this.parse(target);
|
30 | this._tablespecs = tableSpecs;
|
31 | this._schema = sequelizeService.addScheam(this.schemaName, this.parsedSchema, this._tablespecs);
|
32 | if(this._defaultPrimaryKey){
|
33 | this._schema.beforeCreate((user, _ ) => {
|
34 | let id = this['_defaultPrimaryKey'](user);
|
35 | user[this._schema.primaryKeyField] =id;
|
36 | return user;
|
37 | });
|
38 | }
|
39 | }
|
40 |
|
41 | public getSchema() {
|
42 | return this._schema;
|
43 | }
|
44 |
|
45 | public getRelations() {
|
46 | return this._relations;
|
47 | }
|
48 |
|
49 | public getTarget() {
|
50 | return this.target;
|
51 | }
|
52 |
|
53 | private parse(target: Object) {
|
54 | if (!target || !(target instanceof Object)) {
|
55 | throw TypeError;
|
56 | }
|
57 | var schema = {};
|
58 | var primaryKeyProp;
|
59 |
|
60 | var metaDataMap = MetaUtils.getMetaData(this.target, Decorators.COLUMN);
|
61 | for (var field in metaDataMap) {
|
62 | var fieldMetadata: MetaData = <MetaData>metaDataMap[field];
|
63 | let newParam = {}
|
64 | Object.keys(fieldMetadata.params).forEach(x => {
|
65 | if(this._removeColumnProperties.indexOf(x)<0){
|
66 | newParam[x] = fieldMetadata.params[x]
|
67 | }
|
68 | else if(x == 'otherProperties'){
|
69 | Object.keys(fieldMetadata.params[x]).forEach(subProp=>{
|
70 | newParam[subProp] = fieldMetadata.params[x][subProp];
|
71 | });
|
72 | }
|
73 | })
|
74 | if(fieldMetadata.params.primaryKey && typeof fieldMetadata.params.defaultValue=="function"){
|
75 | this._defaultPrimaryKey = fieldMetadata.params.defaultValue;
|
76 | delete newParam['defaultValue'];
|
77 | }
|
78 | schema[fieldMetadata.params.name] = newParam;
|
79 | }
|
80 |
|
81 | var metaDataMap1 = MetaUtils.getMetaData(this.target, Decorators.ONETOMANY);
|
82 | var oneTomanyrels = [];
|
83 | for (var field in metaDataMap1) {
|
84 | var fieldMetadata: MetaData = <MetaData>metaDataMap1[field];
|
85 |
|
86 | var params = fieldMetadata.params;
|
87 | params.propertyKey = fieldMetadata.propertyKey;
|
88 | if (!params.foreignKey)
|
89 | throw 'Please add foreign key for association ' + this.schemaName + ' -> ' + params.propertyKey;
|
90 | oneTomanyrels.push(params);
|
91 | }
|
92 | this._relations[Decorators.ONETOMANY] = oneTomanyrels;
|
93 |
|
94 | var metaDataMap2 = MetaUtils.getMetaData(this.target, Decorators.MANYTOONE);
|
95 | var manytoonerels = [];
|
96 | for (var field in metaDataMap2) {
|
97 | var fieldMetadata: MetaData = <MetaData>metaDataMap2[field];
|
98 |
|
99 | var params = fieldMetadata.params;
|
100 | params.propertyKey = fieldMetadata.propertyKey;
|
101 | if (!params.foreignKey)
|
102 | throw 'Please add foreign key for association ' + this.schemaName + ' -> ' + params.propertyKey;
|
103 | else if (!schema[params.foreignKey])
|
104 | throw 'Please choose a valid foreign key from the defined properties for ' + this.schemaName + ' -> ' + params.propertyKey;
|
105 | manytoonerels.push(params);
|
106 | }
|
107 | this._relations[Decorators.MANYTOONE] = manytoonerels;
|
108 |
|
109 | var metaDataMap3 = MetaUtils.getMetaData(this.target, Decorators.ONETOONE);
|
110 | var onetoonerels = [];
|
111 | for (var field in metaDataMap3) {
|
112 | var fieldMetadata: MetaData = <MetaData>metaDataMap3[field];
|
113 |
|
114 | var params = fieldMetadata.params;
|
115 | params.propertyKey = fieldMetadata.propertyKey;
|
116 | if (!params.foreignKey)
|
117 | throw 'Please add foreign key for association ' + this.schemaName + ' -> ' + params.propertyKey;
|
118 | onetoonerels.push(params);
|
119 | }
|
120 | this._relations[Decorators.ONETOONE] = onetoonerels;
|
121 |
|
122 | return schema;
|
123 | }
|
124 |
|
125 | private getSearchSchemaTypeForParam(fieldMetadata: MetaData): any {
|
126 | var schemaType = this.getSchemaTypeForType(fieldMetadata.getType());
|
127 | if (fieldMetadata.params && fieldMetadata.params.rel) {
|
128 | return fieldMetadata.propertyType.isArray ? [schemaType] : schemaType;
|
129 | }
|
130 | else {
|
131 | return fieldMetadata.propertyType.isArray ? [schemaType] : { type: schemaType, es_indexed: true };
|
132 | }
|
133 |
|
134 |
|
135 |
|
136 |
|
137 |
|
138 |
|
139 |
|
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 | }
|
149 |
|
150 | private getSchemaTypeForParam(fieldMetadata: MetaData) {
|
151 | var schemaType = this.getSchemaTypeForType(fieldMetadata.getType());
|
152 | return fieldMetadata.propertyType.isArray ? [schemaType] : schemaType;
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 |
|
168 | }
|
169 |
|
170 | private getSchemaTypeForType(type?): any {
|
171 | switch (type) {
|
172 | case Mongoose.Types.ObjectId: return Mongoose.Schema.Types.ObjectId;
|
173 | case String: return Sequelize.STRING(128);
|
174 | case Number: return Number;
|
175 | case Buffer: return Buffer;
|
176 | case Date: return Date;
|
177 | case Boolean: return Boolean;
|
178 | case Array: return Array;
|
179 |
|
180 |
|
181 | case Object:
|
182 | default: return Mongoose.Schema.Types.Mixed;
|
183 | }
|
184 | }
|
185 |
|
186 | private getMongooseOptions(target: Object) {
|
187 | var meta = MetaUtils.getMetaData(<any>target, Decorators.ENTITY);
|
188 | var entityMeta = meta[0];
|
189 | var options = <any>{};
|
190 | var params = <IEntityParams>(entityMeta.params || <any>{});
|
191 | options.strict = true;
|
192 | return options;
|
193 | }
|
194 |
|
195 | private isSchemaDecorator(decorator: string) {
|
196 | return decorator === Decorators.FIELD || decorator === Decorators.ONETOMANY || decorator === Decorators.MANYTOONE || decorator === Decorators.MANYTOMANY || decorator === Decorators.ONETOONE;
|
197 | }
|
198 |
|
199 | private getAllMetadataForSchema(target: Object): { [key: string]: MetaData } {
|
200 | var metaDataMap: Array<MetaData> = MetaUtils.getMetaData(<any>target);
|
201 | var metaDataMapFiltered: { [key: string]: MetaData } = <any>{};
|
202 | for (var i in metaDataMap) {
|
203 | var meta: MetaData = metaDataMap[i] as MetaData;
|
204 |
|
205 | if (!this.isSchemaDecorator(meta.decorator))
|
206 | continue;
|
207 |
|
208 | if (metaDataMapFiltered[meta.propertyKey])
|
209 | throw "A property cannot have more than one schema decorator";
|
210 |
|
211 | metaDataMapFiltered[meta.propertyKey] = meta;
|
212 | }
|
213 | return metaDataMapFiltered;
|
214 | }
|
215 | } |
\ | No newline at end of file |