@simitgroup/simpleapp-generator 1.0.55 → 1.0.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simitgroup/simpleapp-generator",
3
- "version": "1.0.55",
3
+ "version": "1.0.57",
4
4
  "description": "frontend nuxtjs and backend nests code generator using jsonschema",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -8,6 +8,7 @@
8
8
  import { UserContext } from '../commons/user.context'
9
9
  import { Injectable } from '@nestjs/common';
10
10
  import { InjectModel } from '@nestjs/mongoose';
11
+ import * as jsonpath from 'jsonpath'
11
12
  import { Model } from 'mongoose';
12
13
  import {<%= it.typename%>JsonSchema } from '../jsonschemas/<%= it.doctype %>.jsonschema'
13
14
  import { SimpleAppService,IsolationType,HookType } from './simpleapp.processor';
@@ -48,80 +49,19 @@ export class <%= it.typename %>Processor extends SimpleAppService<<%= it.typenam
48
49
  }
49
50
 
50
51
 
51
- reCalculateValue(){
52
- console.log('trigger new recalculate')
53
- const data = this.getData()
52
+ reCalculateValue(data:<%= it.typename %>):<%= it.typename %>{
53
+ console.log('trigger new recalculate')
54
+ <% if(it.jsonschema['x-simpleapp-config']['formulas']){ %>
55
+ <%Object.keys(it.jsonschema['x-simpleapp-config']['formulas']).forEach(function(index) { %>
56
+ <% let fml = it.jsonschema['x-simpleapp-config']['formulas'][index] %>
57
+ // <%~ JSON.stringify(fml) %>
58
+ //const tmp = jsonpath.query(vdata,fieldpath).filter((item:string)=>item!='')
59
+
60
+ jsonpath.apply(data, '<%~ fml.jsonpath %>', function(value) { return <%~fml.formula %> });
54
61
 
55
- <%Object.keys(it.jsonschema.properties).forEach(function(key) { %>
56
- <%let obj = it.jsonschema.properties[key]%>
57
- <%if(obj['x-compute']){%> //x-compute first level field
58
-
59
- data.<%=key%> = <%= obj['x-compute'].function %>(
60
- <% if(obj['x-compute'].paramters){ %>
61
- <% let p = obj['x-compute'].paramters %>
62
- <%for(let j=0; j<p.length; j++){%>
63
- <%= p[j].replace('@data','data') %>,
64
- <%}%>
65
- <%}%>
66
- )
67
- <%}%>
68
- <%if(obj.type=='array' && obj.items.type=='object'){%>
69
- // process compute for 2nd level sub tables
70
- for(let index=0;index<data.<%=key%>.length;index++){
71
- <%Object.keys(obj.items.properties).forEach(function(subkey) { %>
72
- <%let subobj = obj.items.properties[subkey]%>
73
- <%if(subobj['x-compute']){%>
74
-
75
- data.<%=key%>[index].<%=subkey%> = <%= subobj['x-compute'].function %>(
76
- <% if(subobj['x-compute'].paramters){ %>
77
- <% let subp = subobj['x-compute'].paramters %>
78
- <%for(let k=0; k<subp.length; k++){%>
79
- <%= subp[k].replace('@data','data').replace('@index','index') %>,
80
- <%}%>
81
- <%}%>
82
- )
83
- <%}%>
84
-
85
- <% if(subobj.type=='array' && subobj.items && subobj.items.type=='object'){ %>
86
- // process compute for 3rd level sub tables
87
- for(let index2=0;index<data.<%=key%>[index].length;index2++){
88
- <%Object.keys(subobj.items.properties).forEach(function(sub2key) { %>
89
- <%let sub2obj = subobj.items.properties[sub2key]%>
90
- <%if(sub2obj['x-compute']){%> //x-compute 3rd level field
91
- data.<%=key%>[index].<%=subkey%>[index2].<%=sub2key%> = <%= sub2obj['x-compute'].function %>(
92
- <% if(sub2obj['x-compute'].paramters){ %>
93
- <% let sub2p = sub2obj['x-compute'].paramters %>
94
- <%for(let l=0; l<sub2p.length; l++){%>
95
- <%= sub2p[l].replace('@data','data').replace('@index','index').replace('@index2','index2') %>,
96
- <%}%>
97
- <%}%>
98
- )
99
- <%}%>
100
- <%if(sub2obj.type=='array' && sub2obj.items && sub2obj.items.type=='object'){%>
101
- // process compute for 4rd level sub tables
102
- for(let index3=0;index<data.<%=key%>[index].<%=subkey%>[index2].length;index3++){
103
- <%Object.keys(sub2obj.items.properties).forEach(function(sub3key) { %>
104
- <%let sub3obj = sub2obj.items.properties[sub3key]%>
105
- <%if(sub3obj['x-compute']){%> //x-compute 4th level field
106
- data.<%=key%>[index].<%=subkey%>[index2].<%=sub2key%>.[index3].<%=sub3key%> = <%= sub3obj['x-compute'].function %>(
107
- <% if(sub3obj['x-compute'].paramters){ %>
108
- <% let sub3p = sub3obj['x-compute'].paramters %>
109
- <%for(let m=0; m<sub3p.length; m++){%>
110
- <%= subp[m].replace('@data','data').replace('@index','index').replace('@index2','index2').replace('@index3','index3') %>,
111
- <%}%>
112
- <%}%>
113
- )
114
- <%}%>
115
-
116
- <%})%>
117
- <%} /* process compute for 4rd level sub tables */%>
118
- <%})%>
119
- }
120
- <%} // process compute for 3rd level sub tables%>
121
- <%}) %>
122
- }
123
- <%} /*process compute for 2nd level sub tables*/%>
124
- <%}) %>
62
+ <%}) %>
63
+ <%} %>
64
+ return data
125
65
  }
126
66
 
127
67
 
@@ -0,0 +1,78 @@
1
+ /**
2
+ * This file was automatically generated by simpleapp generator. Every
3
+ * MODIFICATION OVERRIDE BY GENERATEOR
4
+ * last change 2023-10-31
5
+ * Author: Ks Tan
6
+ *
7
+ * this class developed for implement field level encryption, however it still half way and keep here for future enhancement
8
+ * it doesn't effect anything at the moment
9
+ */
10
+
11
+ import { Injectable } from '@nestjs/common';
12
+ import { createCipheriv,createDecipheriv, randomBytes, scrypt,Cipher,Decipher } from 'crypto';
13
+ import { promisify } from 'util';
14
+
15
+
16
+
17
+ export class Encryption{
18
+ private static instance: Encryption;
19
+ private algorithm = 'aes-256-ctr'
20
+ private iv = randomBytes(16);
21
+ private password = String(process.env.ENRYPTION_KEY)
22
+
23
+ private key :Buffer
24
+
25
+ constructor(){
26
+ this.init();
27
+ }
28
+ public static getInstance(): Encryption {
29
+ if (!Encryption.instance) {
30
+ Encryption.instance = new Encryption();
31
+ }
32
+
33
+ return Encryption.instance;
34
+ }
35
+
36
+
37
+
38
+ async init (){
39
+
40
+
41
+ console.log("Initialized encryption class")
42
+ }
43
+
44
+
45
+ getKey = async (salt)=>{
46
+ const key = (await promisify(scrypt)(this.password,salt , 32)) as Buffer;
47
+ return key
48
+ }
49
+
50
+ encrypt = async (value:string)=>{
51
+ const salt ='salt'
52
+ const key = await this.getKey(salt)
53
+ const cipher = createCipheriv(this.algorithm, key, this.iv);
54
+ console.log("Encrypting text ",value,cipher)
55
+ const encryptedText = Buffer.concat([
56
+ cipher.update(value),
57
+ cipher.final(),
58
+ ]).toString('hex');
59
+ console.log("encryptedText",encryptedText)
60
+ return encryptedText
61
+ }
62
+
63
+ decrypt = async (value:string,salt:string)=>{
64
+ const key = await this.getKey(salt)
65
+ const decipher = createDecipheriv('aes-256-ctr', key, this.iv);
66
+ const buf = Buffer.from(value)
67
+ const decryptedText = Buffer.concat([
68
+ decipher.update(buf),
69
+ decipher.final(),
70
+ ]).toString('hex');
71
+ return decryptedText
72
+
73
+ }
74
+ }
75
+
76
+
77
+
78
+
@@ -29,18 +29,26 @@ export class SimpleAppExceptionFilter implements ExceptionFilter {
29
29
  const session:ClientSession = request['sessionuser'].getDBSession()
30
30
  if(session.inTransaction())session.abortTransaction()
31
31
  }
32
-
32
+ console.log('exceptionexception',typeof exception,Object.keys(exception),exception)
33
+ let errordata
34
+ let finalstatus
35
+ let msg
36
+ if(Object.keys(exception).length>0){
37
+ msg = exception.message
38
+ errordata = (exception.response && exception.response.options) ? exception.response.options : exception.options
39
+ finalstatus = ( exception.response && exception.response.status) ? exception.response.status : exception.status
40
+ }else{
41
+ msg = String(exception)
42
+ finalstatus = 500
43
+ }
33
44
 
34
45
  const responseBody = {
35
- message:exception.message,
46
+ message: msg,
36
47
  timestamp: new Date().toISOString(),
37
48
  path: httpAdapter.getRequestUrl(ctx.getRequest()),
38
- error: exception.response.options?? exception.options
49
+ error:errordata
39
50
  };
40
- // console.log("exception properties", Object.getOwnPropertyNames(exception),exception.options)
41
-
42
- // console.log("exception.responseexception.response",exception)
43
- const finalstatus = exception.response.status??exception.status
51
+
44
52
  const eventObj = request['eventObj']
45
53
  if(eventObj){
46
54
  eventObj.statusCode=finalstatus
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import { Injectable, Logger,Inject } from '@nestjs/common';
8
8
  import { InjectModel } from '@nestjs/mongoose';
9
- import * as jsonpath from 'jsonpath'
9
+ import jsonpath from 'jsonpath'
10
10
  import { uniq } from 'lodash';
11
11
  import { AuditTrail } from '../commons/audittrail.service';
12
12
  import {foreignkeys} from '../commons/dicts/foreignkeys'
@@ -290,14 +290,14 @@ export class SimpleAppService<T extends { _id?: string }> {
290
290
  this.logger.debug("Create data before isolation",'SimpleAppService')
291
291
  this.logger.debug(data,'SimpleAppService')
292
292
  Object.assign(data, isolationFilter);
293
-
293
+ data = this.reCalculateValue(data)
294
294
  await this.validateData(appuser,data);
295
295
  this.logger.debug("Create record",'SimpleAppService')
296
296
  this.logger.debug(data,'SimpleAppService')
297
297
 
298
298
  this.applyNestedDateTime(appuser,data,'create')
299
299
  const newdoc = new this.doc(data);
300
-
300
+ await this.identifyUniqueKeys(appuser,data)
301
301
  try{
302
302
  result = await newdoc.save({session:dbsession})
303
303
  }catch(err){
@@ -464,7 +464,9 @@ export class SimpleAppService<T extends { _id?: string }> {
464
464
  // try {
465
465
  Object.assign(data, appuser.getUpdateFilter());
466
466
  Object.assign(existingdata, data);
467
- delete existingdata['_id']
467
+ delete data['_id']
468
+
469
+ data = this.reCalculateValue(data)
468
470
  // existingdata['_id']=''
469
471
  // console.log("newdata",data)
470
472
  await this.validateData(appuser,data);
@@ -508,7 +510,7 @@ export class SimpleAppService<T extends { _id?: string }> {
508
510
  const collection = this.doc.db.collection(collectionname);
509
511
  //single schema may have multiple foreign key link here, loop all
510
512
  for (let j = 0; j < fobjs.length; j++) {
511
- const fkey = fobjs[j] + '._id';
513
+ const fkey = fobjs[j]
512
514
  let filter = {}
513
515
  filter[fkey] = id;
514
516
 
@@ -579,23 +581,26 @@ export class SimpleAppService<T extends { _id?: string }> {
579
581
 
580
582
  //get all foreign keys catalogue
581
583
  const collections = Object.getOwnPropertyNames(this.foreignkeys)
582
-
584
+ console.log("111111",collections)
583
585
  //obtain exists data in according foreign key
584
586
  const pipelines :PipelineStage[] =[ {$match:{_id:false}}] //exclude data from current collection
585
- const vdata = data['_doc']
587
+ const vdata = data//['_doc']
586
588
  const keystore = {}
587
589
  collections.forEach((collectionname)=>{
588
590
  const fks:string[] = this.foreignkeys[collectionname]
589
591
  let results:string[] = []
590
592
  fks.forEach(fieldpath=>{
593
+ // console.log("fieldpath:",fieldpath,"vdata",data,vdata)
591
594
  const tmp = jsonpath.query(vdata,fieldpath).filter((item:string)=>item!='')
595
+ // console.log("tmp",tmp)
596
+
592
597
  results = results.concat(tmp)
593
598
  })
594
599
 
595
600
 
596
601
 
597
602
  if(results.length>0){
598
- console.log(results)
603
+ console.log('tmp',results)
599
604
  if(results.length>1){
600
605
  results = uniq<string>(results)
601
606
  }
@@ -609,22 +614,24 @@ export class SimpleAppService<T extends { _id?: string }> {
609
614
  pipelines.push(stagefilter)
610
615
  }
611
616
  })
612
-
617
+ this.logger.debug(pipelines,'identifyUniqueKeys')
613
618
  // this.doc.db.collection(collectionname);
614
619
  const unionresult = await this.doc.aggregate(pipelines)
615
620
 
616
621
  if(!unionresult){
622
+ this.logger.error("foreign key control failed ",'identifyUniqueKeys')
617
623
  throw new InternalServerErrorException("Foreignkey check execution error",pipelines as HttpExceptionOptions)
618
624
  }else{
619
625
  let searchresult:any = {}
620
626
  unionresult.forEach(item=>{
627
+ console.log("111")
621
628
  if(searchresult[item.collection]){
622
629
  searchresult[item.collection].push(item._id)
623
630
  }else{
624
631
  searchresult[item.collection] = [item._id]
625
632
  }
626
633
  })
627
-
634
+
628
635
  //search is it all foreign key exists in db
629
636
  for(let i=0; i<collections.length; i++){
630
637
  const collectionname = collections[i]
@@ -634,19 +641,21 @@ export class SimpleAppService<T extends { _id?: string }> {
634
641
  }
635
642
  for(let k=0;k<keys.length; k++){
636
643
  const key = keys[k]
637
- if(!searchresult[collectionname].includes(key)){
638
- console.log(`Foreignkey ${key} at collection ${collectionname} does not exist`)
639
- throw new BadRequestException(`Foreignkey ${key} at collection ${collectionname} does not exist`)
640
- }
644
+ if(searchresult[collectionname] && searchresult[collectionname].includes(key)){
645
+ this.logger.debug(`foreignkey ${collectionname}->${key} exists`)
646
+ }
641
647
  else{
642
- // console.log(`${collectionname} - ${key} found`)
648
+ this.logger.warn(`Foreignkey ${key} at collection ${collectionname} does not exist`,'identifyUniqueKeys')
649
+ const errordata = {key:key,collection:collectionname}
650
+ throw new BadRequestException(`Foreignkey ${key} at collection ${collectionname} does not exist`,JSON.stringify(errordata))
651
+
643
652
  }
644
653
  }
645
654
 
646
655
  }
647
656
 
648
657
  }
649
-
658
+ console.log("666")
650
659
  }
651
660
 
652
661
 
@@ -8,6 +8,7 @@ import { Module } from '@nestjs/common';
8
8
  import { MongooseModule } from '@nestjs/mongoose';
9
9
  import {DocNumberFormatGenerator} from './generate/commons/docnogenerator.service'
10
10
  import { AuditTrail } from './generate/commons/audittrail.service';
11
+
11
12
  // auto import modules
12
13
  <% for(let i=0;i<it.modules.length; i++){ %>
13
14
  <% let obj = it.modules[i]%>
@@ -23,7 +24,7 @@ import { ProfileService } from './profile/profile.service';
23
24
 
24
25
 
25
26
  //<%if(it.doctype != 'autoinc'){%>import {AutoincreamentModule} from '../autoinc/autoinc.module'<%}%>
26
-
27
+ //encryption use for model (not class and cant inject, use singleton instead and init as early as possible)
27
28
 
28
29
  @Module({
29
30
  imports: [
@@ -0,0 +1,7 @@
1
+ {
2
+ // https://nuxt.com/docs/guide/concepts/typescript
3
+ "extends": "./.nuxt/tsconfig.json",
4
+ "compilerOptions": {
5
+ "verbatimModuleSyntax": false
6
+ }
7
+ }