UNPKG

17.6 kBPlain TextView Raw
1import {config,isJSON} from '../core/utils';
2import * as Sequelize from "sequelize";
3import Q = require('q');
4import {IEntityService} from '../core/interfaces/entity-service';
5import {MetaUtils} from "../core/metadata/utils";
6import {pathRepoMap, getEntity} from '../core/dynamic/model-entity';
7import {QueryOptions} from '../core/interfaces/queryOptions';
8import {Decorators as CoreDecorators, Decorators} from '../core/constants';
9import * as Enumerable from 'linq';
10import { IAssociationParams } from '../core/decorators/interfaces';
11import { PrincipalContext } from '../security/auth/principalContext';
12import {ConstantKeys} from '../core/constants/constantKeys';
13var queryString = require('qs');
14
15class SequelizeService implements IEntityService {
16 private sequelize: any;
17 private _schemaCollection = {};
18 private _relationCollection = [];
19 constructor() {
20
21 }
22
23 init(force?: boolean): Promise<any> {
24 force = force || false;
25 return this.sequelize.sync({ force: force, logging: true });
26 }
27
28 connect() {
29 if (config().SqlConfig.isSqlEnabled == false)
30 return;
31 this.sequelize = new Sequelize(config().SqlConfig.database,
32 config().SqlConfig.username,
33 config().SqlConfig.password,
34 config().SqlConfig.sequlizeSetting);
35 }
36
37 getSqlContext(): any {
38 return this.sequelize;
39 }
40
41 startTransaction(param?:any):Q.Promise<any>{
42 return this.sequelize.transaction();
43 }
44
45 commitTransaction(param?:any):Q.Promise<any>{
46 return param.commit();
47 }
48
49 rollbackTransaction(param?:any):Q.Promise<any>{
50 return param.rollback();
51 }
52
53 getCustomResult(databaseName: string, query) {
54 if (config().SqlConfig.isSqlEnabled == false)
55 return;
56 var dynamicSequelize = new Sequelize(databaseName,
57 config().SqlConfig.username,
58 config().SqlConfig.password,
59 config().SqlConfig.sequlizeSetting);
60 return dynamicSequelize.query(query);
61 }
62
63 addScheam(name: string, schema: any, detail: any) {
64 var newSchema = this.sequelize.define(name, schema, detail);
65 this._schemaCollection[name] = newSchema;
66 return newSchema;
67 }
68
69 addRelationInSchema(fromSchema: any, toSchema: any, relationType:string, metaData:IAssociationParams) {
70 let path = metaData.propertyKey;
71 if (relationType == CoreDecorators.ONETOMANY)
72 fromSchema.hasMany(toSchema, { as: path, foreignKey:metaData.foreignKey});
73 if (relationType == CoreDecorators.MANYTOONE)
74 fromSchema.belongsTo(toSchema, { as: path, foreignKey:metaData.foreignKey});
75 if (relationType == CoreDecorators.ONETOONE)
76 fromSchema.hasOne(toSchema, { as: path, foreignKey:metaData.foreignKey});
77
78 let relationToDictionary: any = {};
79 relationToDictionary.metaData = metaData;
80 relationToDictionary.type = relationType;
81 relationToDictionary["relation"] = metaData.rel;
82 relationToDictionary.fromSchema = fromSchema;
83 relationToDictionary.toSchema = toSchema;
84 relationToDictionary.path = path;
85
86 this._relationCollection.push(relationToDictionary);
87 }
88
89 parseProperties(props,schemaModel){
90 let config = {}
91 props.forEach(prop=>{
92 if(prop.indexOf('.')<0){
93 config['attributes']=config['attributes']?config['attributes']:[];
94 config['attributes'].push(prop);
95 }
96 else{
97 let foreignKeys = prop.split('.');
98 this.insertForeignKey(config, foreignKeys,schemaModel);
99 }
100 })
101 return config;
102 }
103
104 insertForeignKey(config, foreignKeys,schemaModel){
105 let modelConfig = config;
106 foreignKeys.forEach((x, i)=>{
107 if(foreignKeys.length-1 == i){
108 modelConfig['attributes']=modelConfig['attributes']?modelConfig['attributes']:[];
109 let relSchemas = this._relationCollection.filter(schema => (schema.relation == schemaModel.name));
110 if(relSchemas.length >0 && relSchemas[0].toSchema.primaryKeyAttribute!=x){
111 modelConfig['attributes'].push(x);
112 }
113 }
114 else{
115 modelConfig['include']=modelConfig['include']?modelConfig['include']:[];
116 let filterConfig = modelConfig.include.filter(p=>p.as==x);
117 if(!filterConfig.length){
118 let relSchemas = this._relationCollection.filter(schema => (schema.fromSchema.name == schemaModel.name) && (schema.type == Decorators.MANYTOONE) && (schema.path == x));
119 if(relSchemas.length>0){
120 schemaModel = relSchemas[0].toSchema;
121 let tempConfig = { model: relSchemas[0].toSchema, as :relSchemas[0].path,attributes:[relSchemas[0].toSchema.primaryKeyAttribute]}
122 modelConfig.include.push(tempConfig);
123 modelConfig = tempConfig;
124 }
125 }
126 else{
127 let relSchemas = this._relationCollection.filter(schema => (schema.fromSchema.name == schemaModel.name) && (schema.type == Decorators.MANYTOONE) && (schema.path == x));
128 if(relSchemas.length>0){
129 schemaModel = relSchemas[0].toSchema;
130 }
131 modelConfig = filterConfig[0];
132 }
133 }
134 })
135 }
136
137 getAllForeignKeyAssocationsForFindWhere(inputArr, schemaModel) {
138 let parseProperties = this.parseProperties(inputArr,schemaModel);
139 return parseProperties;
140 }
141
142 getAllForeignKeyAssocations(schemaModel, properties:Array<string>){
143 let includes = [];
144 let relSchemas = this._relationCollection.filter(x=>(x.fromSchema.name == schemaModel.name) && (x.type == Decorators.MANYTOONE ));
145 if(relSchemas.length){
146 relSchemas.forEach(x=>{
147 if(!properties || !properties.length || properties.indexOf(x.path)>=0){
148 if(x.metaData.eagerLoading){
149 let model = { model: x.toSchema, as: x.path};
150 if (x.metaData.properties) {
151 model['attributes'] = x.metaData.properties;
152 }
153 let childModel = this.getAllForeignKeyAssocations(x.toSchema, x.metaData.properties);
154 if(childModel.length){
155 model['include']= childModel;
156 }
157 includes.push(model);
158 }
159 }
160 });
161 }
162 return includes;
163 }
164
165 getAllForeignKeyAssocationsForManyToOne(schemaModel, properties:Array<string>){
166 let includes = [];
167 let relSchemas = this._relationCollection.filter(x=>(x.fromSchema.name == schemaModel.name) && (x.type == Decorators.MANYTOONE));
168 if(relSchemas.length){
169 relSchemas.forEach(x=>{
170 if(!properties || !properties.length || properties.indexOf(x.path)>=0){
171 if(x.metaData.eagerLoading){
172 let model = { model: x.toSchema, as: x.path};
173 if (x.metaData.properties) {
174 model['attributes'] = x.metaData.properties;
175 }
176 let childModel = this.getAllForeignKeyAssocationsForManyToOne(x.toSchema, x.metaData.properties);
177 if(childModel.length){
178 model['include']= childModel;
179 }
180 includes.push(model);
181 }
182 }
183 });
184 }
185 return includes;
186 }
187
188 getAllForeignKeyAssocationsOneToMany(type, schemaModel, properties:Array<string>){
189 let includes = [];
190 let relSchemas = this._relationCollection.filter(x=>(x.fromSchema.name == schemaModel.name) && ( x.type == type));
191 if(relSchemas.length){
192 relSchemas.forEach(x=>{
193 if(!properties || !properties.length || properties.indexOf(x.path)>=0){
194 if(x.metaData.eagerLoading){
195 let model = { model: x.toSchema, as: x.path};
196 if (x.metaData.properties) {
197 model['attributes'] = x.metaData.properties;
198 }
199 let childModel = this.getAllForeignKeyAssocationsOneToMany(type, x.toSchema, x.metaData.properties);
200 if(childModel.length){
201 model['include']= childModel;
202 }
203 includes.push(model);
204 }
205 }
206 });
207 }
208 return includes;
209 }
210
211 getModel(repoPath: string, dynamicName?: string) {
212 try {
213 var schemaNamefromPathRepomap = pathRepoMap[repoPath].schemaName;
214 return this._schemaCollection[schemaNamefromPathRepomap];
215 } catch (e) {
216 throw e;
217 }
218 }
219
220 appendTransaction(options){
221 let trans = PrincipalContext.get(ConstantKeys.transaction);
222 if(trans){
223 options['transaction'] = trans;
224 }
225 return options;
226 }
227
228 bulkPost(repoPath: string, objArr: Array<any>, batchSize?: number): Q.Promise<any> {
229 let options = {individualHooks: true}
230 options = this.appendTransaction(options);
231 return this.getModel(repoPath).bulkCreate(objArr, options).then(result=>{
232 return result.map(x=>x.dataValues);
233 });
234 }
235
236 bulkPutMany(repoPath: string, objIds: Array<any>, obj: any): Q.Promise<any> {
237 let primaryKey = this.getModel(repoPath).primaryKeyAttribute;
238 let cond = {}
239 cond[primaryKey] = objIds
240 let options = { where: cond };
241 options = this.appendTransaction(options);
242 return this.getModel(repoPath).update(obj, options).then(result=>{
243 return this.findMany(repoPath, objIds, false);
244 });
245 }
246
247 bulkDel(repoPath: string, objArr: Array<any>): Q.Promise<any> {
248 let primaryKey = this.getModel(repoPath).primaryKeyAttribute;
249 let cond = {}
250 if(isJSON(objArr[0])){
251 cond[primaryKey] = objArr.map(x => x[primaryKey]);
252 }
253 else{
254 cond[primaryKey] = objArr;
255 }
256 let options = { where: cond }
257 options = this.appendTransaction(options);
258 return this.getModel(repoPath).destroy(options).then(result=>{
259 return {success:result};
260 })
261 }
262
263 bulkPut(repoPath: string, objArr: Array<any>,batchSize?: number): Q.Promise<any> {
264 let asyncalls=[];
265 let primaryKey = this.getModel(repoPath).primaryKeyAttribute;
266 objArr.forEach(obj=>{
267 let cond = {}
268 cond[primaryKey] = obj[primaryKey];
269 let options = { where: cond }
270 options = this.appendTransaction(options);
271 asyncalls.push(this.getModel(repoPath).update(obj, options));
272 });
273 return Q.allSettled(asyncalls).then(result=>{
274 return this.findMany(repoPath, objArr.map(x=>x[primaryKey]), false);
275 });
276 }
277
278 bulkPatch(repoPath: string, objArr: Array<any>): Q.Promise<any> {
279 return this.bulkPut(repoPath, objArr);
280 }
281
282 findAll(repoPath: string): Q.Promise<any> {
283 return this.getModel(repoPath).findAll({raw: true}).then(result => {
284 if (!result) return null;
285 //var finalOutput = Enumerable.from(result).select((x:any) => x.dataValues).toArray();// result.forEach(x => x.dataValues).toArray();
286 return result;
287 });
288 }
289
290 findWhere(repoPath: string, query, selectedFields?: Array<string>, queryOptions?: QueryOptions, toLoadChilds?: boolean): Q.Promise<any> {
291 let schemaModel = this.getModel(repoPath);
292 let cond = {};
293 if (selectedFields && selectedFields.length > 0) {
294 cond = this.getAllForeignKeyAssocationsForFindWhere(selectedFields, schemaModel);
295 }
296 else {
297 cond['include'] = this.getAllForeignKeyAssocations(schemaModel, []);
298 }
299 cond["where"] = query
300 if(queryOptions){
301 if(queryOptions.skip){
302 cond['offset'] = parseInt(queryOptions.skip.toString());
303 }
304 if(queryOptions.limit){
305 cond['limit'] = parseInt(queryOptions.limit.toString());
306 }
307 if(queryOptions.sort){
308 cond['order'] = queryOptions.sort
309 }
310 }
311 return schemaModel.findAll(cond).then(result => {
312 if (!result) return null;
313 return result.map(x => x.dataValues);
314 });
315 }
316
317 //This is not testest yet
318 //TODO: add test case for this
319 countWhere(repoPath: string, query): Q.Promise<any> {
320 return this.getModel(repoPath).findAndCountAll({ where: query }).then(result => {
321 return result;
322 });
323 }
324
325
326 //This is not testest yet
327 //TODO: add test case for this
328 distinctWhere(repoPath: string, query): Q.Promise<any> {
329 if (!query) {
330 query = {};
331 }
332 query.distinct = true;
333 return this.getModel(repoPath).findAndCountAll(query).then(result => {
334 return result;
335 });
336 }
337
338 findOne(repoPath: string, id, donotLoadChilds?: boolean): Q.Promise<any> {
339 let schemaModel = this.getModel(repoPath);
340 let primaryKey = schemaModel.primaryKeyAttribute;
341 var cond = {};
342 cond[primaryKey] = id;
343 let include1 = donotLoadChilds? [] : this.getAllForeignKeyAssocationsForManyToOne(schemaModel, null);
344 let include2 = donotLoadChilds? [] : this.getAllForeignKeyAssocationsOneToMany(Decorators.ONETOMANY, schemaModel, null);
345 let include3 = donotLoadChilds? [] : this.getAllForeignKeyAssocationsOneToMany(Decorators.ONETOONE, schemaModel, null);
346 let include = include1.concat(include2).concat(include3);
347 console.log('%%%%%%%%%%%%%%%%%%%%'+include);
348 return schemaModel.find({ include: include, where: cond }).then(result => {
349 return result.dataValues;
350 })
351 .catch(err=>{
352 console.log('####'+err)
353 })
354 }
355
356 findByField(repoPath: string, fieldName, value): Q.Promise<any> {
357 return this.getModel(repoPath).find({ where: { fieldName: value } });
358 }
359
360 findMany(repoPath: string, ids: Array<any>, toLoadEmbeddedChilds?: boolean) {
361 let primaryKey = this.getModel(repoPath).primaryKeyAttribute;
362 let cond = {};
363 cond[primaryKey] = ids;
364 return this.findWhere(repoPath,cond, [], null, toLoadEmbeddedChilds);
365 }
366
367 findChild(repoPath: string, id, prop): Q.Promise<any> {
368 let primaryKey = this.getModel(repoPath).primaryKeyAttribute;
369 let cond = {};
370 cond[primaryKey] = id;
371 return this.getModel(repoPath).find({
372 where: cond,
373 include: [
374 { model: this.getModel(prop), as: prop }
375 ]
376 }).then(
377 function (entity) {
378 return entity[prop];
379 });
380 }
381
382 /**
383 * case 1: all new - create main item and child separately and embed if true
384 * case 2: some new, some update - create main item and update/create child accordingly and embed if true
385 * @param obj
386 */
387 post(repoPath: string, obj: any): Q.Promise<any> {
388 let options = {};
389 options = this.appendTransaction(options);
390 return this.getModel(repoPath).create(obj, options);
391 }
392
393 put(repoPath: string, id: any, obj: any): Q.Promise<any> {
394 let primaryKey = this.getModel(repoPath).primaryKeyAttribute;
395 let cond = {};
396 cond[primaryKey] = id;
397 let options = { where: cond }
398 options = this.appendTransaction(options);
399 return this.getModel(repoPath).update(obj, options).then(result=>{
400 return this.findOne(repoPath, id);
401 })
402 }
403
404 del(repoPath: string, id: any): Q.Promise<any> {
405 let primaryKey = this.getModel(repoPath).primaryKeyAttribute;
406 let cond = {};
407 cond[primaryKey] = id;
408 let options = { where: cond };
409 options = this.appendTransaction(options);
410 return this.getModel(repoPath).destroy(options).then(result=>{
411 return {success:result};
412 })
413 }
414
415 patch(repoPath: string, id: any, obj): Q.Promise<any> {
416 return this.put(repoPath, id, obj)
417 }
418
419 getSortCondition(val){
420 return JSON.parse(val);
421 }
422
423 getLikeCondition(val){
424 val = queryString.parse('key='+val)['key'];
425 return {
426 [this.sequelize.Op.like]: '%'+val+'%'
427 }
428 }
429
430 getStartsWithCondition(val){
431 val = queryString.parse('key='+val)['key'];
432 return {
433 [this.sequelize.Op.like]: val+'%'
434 }
435 }
436
437 getPrimaryKey(repoPath){
438 return this.getModel(repoPath).primaryKeyAttribute;
439 }
440
441 private getAssociationForSchema(model: any, schema: any) {
442 Enumerable.from(this._relationCollection)
443 .where(relationSchema => relationSchema.fromSchema == schema).forEach(relation1 => {
444 model.dataValues[relation1.path] = model[relation1.toSchema.name + "s"];
445 });
446 }
447
448}
449export var sequelizeService = new SequelizeService();
450//export var connect = sequelizeService.connect;