@simitgroup/simpleapp-generator 1.6.6-u-alpha → 1.6.6-w-alpha

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/ReleaseNote.md CHANGED
@@ -1,3 +1,10 @@
1
+ [1.6.6w-alpha]
2
+ 1. Beautify webhooklog body histories
3
+
4
+
5
+ [1.6.6v-alpha]
6
+ 1. Fix webhook no store logs, and add api to obtain webhook execution histories
7
+
1
8
  [1.6.6u-alpha]
2
9
  1. Fix repo crash
3
10
 
@@ -1 +1 @@
1
- {"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/buildinschemas/webhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA8B,MAAM,SAAS,CAAC;AAEjE,eAAO,MAAM,OAAO,EAAE,UAsIrB,CAAA"}
1
+ {"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/buildinschemas/webhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA8B,MAAM,SAAS,CAAC;AAEjE,eAAO,MAAM,OAAO,EAAE,UA+IrB,CAAA"}
@@ -10,7 +10,17 @@ exports.webhook = {
10
10
  "isolationType": type_1.IsolationType.branch,
11
11
  "uniqueKey": "title",
12
12
  "documentTitle": "title",
13
- "resourceName": "webhook"
13
+ "resourceName": "webhook",
14
+ additionalApis: [
15
+ {
16
+ action: 'getHistories',
17
+ entryPoint: ':id/histories',
18
+ requiredRole: ["Admin"],
19
+ method: type_1.RESTMethods.get,
20
+ responseType: '[Webhooklog]',
21
+ description: 'Get webhook execute histories'
22
+ }
23
+ ]
14
24
  },
15
25
  "required": [
16
26
  "title",
@@ -1 +1 @@
1
- {"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/buildinschemas/webhook.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/buildinschemas/webhook.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"webhooklog.d.ts","sourceRoot":"","sources":["../../src/buildinschemas/webhooklog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA8B,MAAM,SAAS,CAAC;AAEjE,eAAO,MAAM,UAAU,EAAE,UAwExB,CAAA"}
1
+ {"version":3,"file":"webhooklog.d.ts","sourceRoot":"","sources":["../../src/buildinschemas/webhooklog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA8B,MAAM,SAAS,CAAC;AAEjE,eAAO,MAAM,UAAU,EAAE,UA4ExB,CAAA"}
@@ -13,6 +13,7 @@ exports.webhooklog = {
13
13
  },
14
14
  "required": [
15
15
  "title",
16
+ "webHookId",
16
17
  "body",
17
18
  "msg"
18
19
  ],
@@ -20,6 +21,9 @@ exports.webhooklog = {
20
21
  "_id": {
21
22
  "type": "string"
22
23
  },
24
+ "webHookId": {
25
+ "type": "string"
26
+ },
23
27
  "created": {
24
28
  "type": "string"
25
29
  },
@@ -1 +1 @@
1
- {"version":3,"file":"webhooklog.js","sourceRoot":"","sources":["../../src/buildinschemas/webhooklog.ts"],"names":[],"mappings":";;;AAAA,kCAAiE;AAEpD,QAAA,UAAU,GAAe;IACpC,MAAM,EAAE,QAAQ;IAChB,oBAAoB,EAAE;QACpB,cAAc,EAAE,YAAY;QAC5B,cAAc,EAAE,YAAY;QAC5B,eAAe,EAAE,oBAAa,CAAC,MAAM;QACrC,WAAW,EAAE,KAAK;QAClB,cAAc,EAAE,YAAY;KAC7B;IACD,UAAU,EAAE;QACV,OAAO;QACP,MAAM;QACN,KAAK;KACN;IACD,YAAY,EAAE;QACZ,KAAK,EAAE;YACL,MAAM,EAAE,QAAQ;SACjB;QACD,SAAS,EAAE;YACT,MAAM,EAAE,QAAQ;SACjB;QACD,SAAS,EAAE;YACT,MAAM,EAAE,QAAQ;SACjB;QACD,WAAW,EAAE;YACX,MAAM,EAAE,QAAQ;SACjB;QACD,WAAW,EAAE;YACX,MAAM,EAAE,QAAQ;SACjB;QACD,UAAU,EAAE;YACV,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,CAAC;YACZ,SAAS,EAAE,CAAC;SACb;QACD,OAAO,EAAE;YACP,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,CAAC;YACZ,SAAS,EAAE,CAAC;SACb;QACD,UAAU,EAAE;YACV,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,CAAC;YACZ,SAAS,EAAE,CAAC;SACb;QACD,OAAO,EAAE;YACP,MAAM,EAAE,QAAQ;YAChB,WAAW,EAAE,CAAC;SACf;QACD,UAAU,EAAE;YACV,MAAM,EAAE,QAAQ;SACjB;QACD,YAAY,EAAE;YACZ,MAAM,EAAE,QAAQ;SACjB;QACD,YAAY,EAAE;YACZ,MAAM,EAAE,QAAQ;SACjB;QACD,QAAQ,EAAE;YACR,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAC,CAAC,SAAS,EAAC,QAAQ,CAAC;SAC5B;QACD,MAAM,EAAE;YACN,MAAM,EAAE,QAAQ;YAChB,QAAQ,EAAC,MAAM;YACf,WAAW,EAAC,CAAC;SACd;QACD,KAAK,EAAC;YACJ,MAAM,EAAC,QAAQ;SAChB;KAEF;CACF,CAAA"}
1
+ {"version":3,"file":"webhooklog.js","sourceRoot":"","sources":["../../src/buildinschemas/webhooklog.ts"],"names":[],"mappings":";;;AAAA,kCAAiE;AAEpD,QAAA,UAAU,GAAe;IACpC,MAAM,EAAE,QAAQ;IAChB,oBAAoB,EAAE;QACpB,cAAc,EAAE,YAAY;QAC5B,cAAc,EAAE,YAAY;QAC5B,eAAe,EAAE,oBAAa,CAAC,MAAM;QACrC,WAAW,EAAE,KAAK;QAClB,cAAc,EAAE,YAAY;KAC7B;IACD,UAAU,EAAE;QACV,OAAO;QACP,WAAW;QACX,MAAM;QACN,KAAK;KACN;IACD,YAAY,EAAE;QACZ,KAAK,EAAE;YACL,MAAM,EAAE,QAAQ;SACjB;QACD,WAAW,EAAE;YACX,MAAM,EAAE,QAAQ;SACjB;QACD,SAAS,EAAE;YACT,MAAM,EAAE,QAAQ;SACjB;QACD,SAAS,EAAE;YACT,MAAM,EAAE,QAAQ;SACjB;QACD,WAAW,EAAE;YACX,MAAM,EAAE,QAAQ;SACjB;QACD,WAAW,EAAE;YACX,MAAM,EAAE,QAAQ;SACjB;QACD,UAAU,EAAE;YACV,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,CAAC;YACZ,SAAS,EAAE,CAAC;SACb;QACD,OAAO,EAAE;YACP,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,CAAC;YACZ,SAAS,EAAE,CAAC;SACb;QACD,UAAU,EAAE;YACV,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,CAAC;YACZ,SAAS,EAAE,CAAC;SACb;QACD,OAAO,EAAE;YACP,MAAM,EAAE,QAAQ;YAChB,WAAW,EAAE,CAAC;SACf;QACD,UAAU,EAAE;YACV,MAAM,EAAE,QAAQ;SACjB;QACD,YAAY,EAAE;YACZ,MAAM,EAAE,QAAQ;SACjB;QACD,YAAY,EAAE;YACZ,MAAM,EAAE,QAAQ;SACjB;QACD,QAAQ,EAAE;YACR,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAC,CAAC,SAAS,EAAC,QAAQ,CAAC;SAC5B;QACD,MAAM,EAAE;YACN,MAAM,EAAE,QAAQ;YAChB,QAAQ,EAAC,MAAM;YACf,WAAW,EAAC,CAAC;SACd;QACD,KAAK,EAAC;YACJ,MAAM,EAAC,QAAQ;SAChB;KAEF;CACF,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simitgroup/simpleapp-generator",
3
- "version": "1.6.6u-alpha",
3
+ "version": "1.6.6w-alpha",
4
4
  "description": "frontend nuxtjs and backend nests code generator using jsonschema",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -8,7 +8,16 @@ export const webhook: SchemaType = {
8
8
  "isolationType":IsolationType.branch,
9
9
  "uniqueKey": "title",
10
10
  "documentTitle": "title",
11
- "resourceName": "webhook"
11
+ "resourceName": "webhook",
12
+ additionalApis: [
13
+ {
14
+ action: 'getHistories',
15
+ entryPoint: ':id/histories',
16
+ requiredRole: ["Admin"],
17
+ method: RESTMethods.get,
18
+ responseType: '[Webhooklog]',
19
+ description: 'Get webhook execute histories'
20
+ }]
12
21
  },
13
22
  "required": [
14
23
  "title",
@@ -11,6 +11,7 @@ export const webhooklog: SchemaType = {
11
11
  },
12
12
  "required": [
13
13
  "title",
14
+ "webHookId",
14
15
  "body",
15
16
  "msg"
16
17
  ],
@@ -18,6 +19,9 @@ export const webhooklog: SchemaType = {
18
19
  "_id": {
19
20
  "type": "string"
20
21
  },
22
+ "webHookId": {
23
+ "type": "string"
24
+ },
21
25
  "created": {
22
26
  "type": "string"
23
27
  },
@@ -4,10 +4,10 @@
4
4
  * last change 2024-03-17
5
5
  * Author: Ks Tan
6
6
  */
7
- import { BadRequestException, Injectable,Inject, InternalServerErrorException, Logger, NotFoundException } from '@nestjs/common';
7
+ import { BadRequestException, Injectable, Inject, InternalServerErrorException, Logger, NotFoundException } from '@nestjs/common';
8
8
  import { EventEmitter2, OnEvent } from '@nestjs/event-emitter';
9
9
  import { UserContext } from './user.context';
10
- import { Webhook,Webhooklog } from '../types';
10
+ import { Webhook, Webhooklog } from '../types';
11
11
  import { alldocuments } from 'src/simpleapp/generate/commons/dicts/documents';
12
12
 
13
13
  @Injectable()
@@ -16,155 +16,157 @@ export class RunWebhookService {
16
16
  protected eventEmitter: EventEmitter2;
17
17
 
18
18
  protected logger = new Logger();
19
- protected maxRetries = 5
19
+ protected maxRetries = 5;
20
20
  public constructor() {}
21
21
 
22
-
23
-
24
22
  /**
25
23
  * trigger
26
24
  */
27
25
  async run(appuser: UserContext, documentName: string, actionName: string, data: any) {
28
- return await this.runRealtimeWebHook(appuser,documentName,actionName,data)
26
+ if (process.env.WEBHOOK_ONOFF && process.env.WEBHOOK_ONOFF.toLowerCase() == 'on') return await this.runRealtimeWebHook(appuser, documentName, actionName, data);
27
+ else this.logger.warn(`Webhook off, not run for ${documentName}:${actionName}`);
29
28
  }
30
- /**
31
- * get/delete
32
- * http://myendpoint.com/{orgid}/invoice/{documentid}/delete
33
- * http://myendpoint.com/{orgid}/invoice/{documentid}?action=delete
34
- *
35
- * post/put/patch
36
- * http://myendpoint.com/{orgid}/invoice/{documentid}
37
- * {json body}
38
- */
29
+
39
30
  async runRealtimeWebHook(appuser: UserContext, documentName: string, actionName: string, data: any) {
40
31
  this.logger.debug(`Run webhook ${documentName}, ${actionName}`);
41
- // console.log(`Run webhook ${documentName}, ${actionName}`);
42
-
43
32
 
44
- const webhooks = appuser.getWebHooks().filter(wh=>
45
- wh.resourceName==documentName && wh.eventType==actionName
46
- )
33
+ const webhooks = appuser.getWebHooks().filter((wh) => wh.resourceName == documentName && wh.eventType == actionName);
47
34
  // console.log(webhooks);
48
-
49
- //same resource,actionName may have multiple webhook, run 1 by 1
50
- for(let whNo=0;whNo<webhooks.length;whNo++){
51
35
 
52
- const webhook = webhooks[whNo]
53
- const reqMethod = webhook.requestMethod
54
- this.logger.verbose(webhook)
36
+ const systemVars = {
37
+ $xOrg: appuser.getXOrg(),
38
+ $accessToken: appuser.getUserToken(),
39
+ $fullName: appuser.getFullname(),
40
+ $email: appuser.getEmail(),
41
+ $uid: appuser.getUid(),
42
+ $resourceName: documentName,
43
+ $actionName: actionName,
44
+ $url: process.env.APP_URL ?? 'http://localhost:8080',
45
+ };
46
+
47
+ //same resource,actionName may have multiple webhook, run 1 by 1
48
+ for (let whNo = 0; whNo < webhooks.length; whNo++) {
49
+ const webhook = webhooks[whNo];
50
+ //danger!! system webhook, only private webhook will allow access
51
+ if (webhook._id.includes('private.')) systemVars['$automationApiKey'] = process.env.DEFAULT_AUTOMATION_API_KEY ?? '';
52
+
53
+ const reqMethod = webhook.requestMethod;
54
+ let webhookUrl = webhook.url;
55
+ // this.logger.verbose(webhook);
55
56
  const headers = {};
56
-
57
+
58
+ Object.keys(systemVars).forEach((k) => {
59
+ webhookUrl = webhookUrl.replace('{{' + k + '}}', systemVars[k]);
60
+ });
61
+
57
62
  if (Array.isArray(webhook.headers)) {
58
63
  webhook.headers.forEach((h) => {
59
- h.value = h.value.replace('{{access_token}}',appuser.getUserToken())
60
- headers[h.name] = h.value;
64
+ let headerValue = h.value ?? '';
65
+ Object.keys(systemVars).forEach((k) => {
66
+ headerValue = headerValue.replace('{{' + k + '}}', systemVars[k]);
67
+ });
68
+
69
+ headers[h.name] = headerValue;
61
70
  });
62
71
  }
63
72
  headers['accept'] = 'application/json';
64
73
  headers['content-type'] = 'application/json';
65
- headers['x-org']=appuser.getXOrg()
66
- headers['x-resource-name']=documentName
67
- headers['x-action-name']=actionName
68
-
69
- if(webhook.authentication=='basic')
70
- headers['Authorization']= 'Basic ' + Buffer.from(webhook.basicAuth.user + ":" + webhook.basicAuth.password).toString('base64');
71
-
72
- let tries = webhook.retryAttemps ?? 0
73
- //first try need + 1
74
- tries = tries+1
75
- //hardcode max retries
76
- if(tries > this.maxRetries) tries = this.maxRetries
77
- const options:RequestInit = {
74
+
75
+ if (webhook.authentication == 'basic') headers['Authorization'] = 'Basic ' + Buffer.from(webhook.basicAuth.user + ':' + webhook.basicAuth.password).toString('base64');
76
+
77
+ let tries: number = webhook.retryAttemps ?? 0;
78
+
79
+ tries = tries + 1;
80
+
81
+ if (tries > this.maxRetries) tries = this.maxRetries;
82
+ const maxtries = tries;
83
+ const options: RequestInit = {
78
84
  method: reqMethod.toUpperCase(),
79
85
  headers: headers,
80
-
81
86
  };
82
- try {
83
- if(['POST','PUT','PATCH'].includes(options.method)){
84
- options.body= this.prepareBody(webhook,data)
85
- }
86
-
87
87
 
88
+ // console.log("options",options)
88
89
 
89
-
90
- while(tries>0){
91
- tries--
92
- console.log("Excute webhook id",webhook._id)
93
- const req = await fetch(webhook.url, options);
94
- const statusCode = req.status;
95
-
90
+ if (['POST', 'PUT', 'PATCH'].includes(options.method)) {
91
+ options.body = this.prepareBody(appuser, webhook, data, systemVars);
92
+ }
96
93
 
97
-
94
+ while (tries > 0) {
95
+ // console.log(`Excute webhook id ${webhook._id} max ${tries}`);
96
+ tries--;
97
+ let req: Response;
98
+ let msg = '';
99
+ let statusCode = 0;
100
+ const tryno = maxtries - tries;
101
+ try {
102
+ req = await fetch(webhookUrl, options);
103
+ statusCode = req.status;
104
+ //sucess, break and no more retry
105
+ msg = `Try: ${tryno}/${maxtries} ${documentName}:${actionName}, ${reqMethod} ${webhookUrl}, ${statusCode},${req.statusText}`;
98
106
  if (statusCode >= 200 && statusCode <= 300) {
99
107
  //success, continue next webhook
100
- const msg = `webhook triggered successfully for ${documentName}:${actionName}. ${reqMethod} ${webhook.url}, try:${tries}, ${statusCode},${req.statusText}`
101
- this.addLog(appuser,documentName,webhook,actionName,data,options,"success",statusCode,msg)
108
+ this.addLog(appuser, documentName, webhook, actionName, data, options, 'success', statusCode, msg);
102
109
  break;
103
- }else if(tries<=0 && webhook.jobType=='roll-back-when-failed'){
104
- //failed, trigger server error for roll back
105
- const msg = `webhook faied, data roll back ${documentName}:${actionName}. ${reqMethod} ${webhook.url}, try:${tries}, ${statusCode},${req.statusText}`
106
- this.addLog(appuser,documentName,webhook,actionName,data,options,'failed',statusCode,msg)
107
- throw new InternalServerErrorException(msg);
108
- }else if(tries<=0 && webhook.jobType=='realtime'){
109
- //failed, but no need to trigger server error/rollback
110
- const msg = `webhook failed, ${documentName}:${actionName}. ${reqMethod} ${webhook.url}, try:${tries}, ${statusCode},${req.statusText}`
111
- this.addLog(appuser,documentName,webhook,actionName,data,options,'failed',statusCode,msg)
112
- }else{
113
- //failed, but still continue retry
114
- const msg = `webhook ${documentName}:${actionName}. ${reqMethod} ${webhook.url}, try:${tries}, ${statusCode},${req.statusText}`
115
- this.addLog(appuser,documentName,webhook,actionName,data,options,'warn',statusCode,msg)
110
+ } else {
111
+ //common error like 404
112
+ this.addLog(appuser, documentName, webhook, actionName, data, options, 'failed', statusCode, msg);
116
113
  }
117
-
114
+ } catch (e) {
115
+ // exception, usually server not accessible. use error 500
116
+ msg = `Try: ${tryno}/${maxtries}, error ${documentName}:${actionName} (${webhook._id}) ${e} at ${webhookUrl}`;
117
+ this.addLog(appuser, documentName, webhook, actionName, data, options, 'failed', 500, msg);
118
118
  }
119
119
 
120
- // const body = req.body;
121
- } catch (e) {
122
- throw new InternalServerErrorException(e);
123
- }
124
-
125
- }
120
+ //finish tries, throw error
121
+ if (tries == 0 && webhook.jobType == 'roll-back-when-failed') {
122
+ throw new InternalServerErrorException(msg);
123
+ }
124
+ } //end retries
125
+ } //next webhook
126
126
 
127
- return true
127
+ return true;
128
128
  }
129
129
 
130
-
131
- addLog(appuser: UserContext, documentName: string, webhook:Webhook, actionName: string, data: any,options,status:string,statusCode:number,msg:string){
132
-
133
-
134
- if(status=='warn'){
135
- status="failed"
136
- this.logger.warn(msg)
130
+ addLog(appuser: UserContext, documentName: string, webhook: Webhook, actionName: string, data: any, options, status: string, statusCode: number, msg: string) {
131
+ if (status == 'success') {
132
+ this.logger.debug(msg);
133
+ } else {
134
+ this.logger.warn(msg);
137
135
  }
138
- else if(status=='success')
139
- this.logger.debug(msg)
140
- else
141
- this.logger.error (msg)
136
+ const logbody = options.body;
137
+ let body = JSON.stringify(logbody, );
142
138
 
143
- let body = JSON.stringify(options,null,4)
144
-
145
139
  const whlog: Webhooklog = {
140
+ _id: crypto.randomUUID(),
141
+ tenantId: appuser.getTenantId(),
142
+ orgId: appuser.getOrgId(),
143
+ branchId: appuser.getBranchId(),
144
+ webHookId: webhook._id,
145
+ created: new Date().toISOString(),
146
+ createdBy: appuser.getUid(),
146
147
  title: `${webhook.requestMethod} ${webhook.url}`,
147
148
  resource: documentName,
148
149
  actionName: actionName,
149
150
  status: status,
150
151
  statusCode: statusCode,
151
- body: body,
152
- msg:msg
153
- }
152
+ body: logbody,
153
+ msg: msg,
154
+ };
154
155
 
155
- this.eventEmitter.emit('webhooklog.add', appuser,whlog);
156
+ this.eventEmitter.emit('webhooklog.add', appuser, whlog);
156
157
  }
157
- prepareBody(webhook:Webhook,data:any){
158
- const cleandata = JSON.parse(JSON.stringify(data))
158
+ prepareBody(appuser: UserContext, webhook: Webhook, data: any, systemVars: any) {
159
+ const cleandata = JSON.parse(JSON.stringify(data));
159
160
 
160
- if(webhook.body?.trim()=='*'){
161
- return JSON.stringify(cleandata)
161
+ if (webhook.body?.trim() == '*') {
162
+ return JSON.stringify(cleandata);
162
163
  }
163
- const parse = require('json-templates');
164
- const template = parse(webhook.body);
165
- const x:BodyInit =template(cleandata)
166
- // this.logger.log(x)
167
- return JSON.parse(JSON.stringify(x))
168
- }
169
-
164
+ const finaldata = { ...cleandata, ...systemVars };
165
+
166
+ const parse = require('json-templates');
167
+ const template = parse(webhook.body);
168
+ const x: BodyInit = template(finaldata);
169
+ // this.logger.log(x)
170
+ return JSON.parse(JSON.stringify(x));
171
+ }
170
172
  }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * This file was automatically generated by simpleapp generator. Every
3
+ * MODIFICATION OVERRIDE BY GENERATEOR
4
+ * last change 2024-07-10
5
+ * Author: Ks Tan
6
+ * Last Modified By: Yong Xiang
7
+ */
8
+ import { UserContext } from '../commons/user.context';
9
+ import * as sharelibs from '../sharelibs';
10
+ import { Injectable } from '@nestjs/common';
11
+ import { InjectModel } from '@nestjs/mongoose';
12
+ import jsonpath from 'jsonpath';
13
+ import { Model } from 'mongoose';
14
+ import { WebhooklogJsonSchema } from '../jsonschemas/webhooklog.jsonschema';
15
+ import { SimpleAppService } from './simpleapp.processor';
16
+ import { IsolationType } from '../types';
17
+ import { DocNumberFormatGenerator } from '../commons/docnogenerator.service';
18
+ import { Webhooklog } from '../types/webhooklog.type';
19
+ import { DefaultWebhooklog } from '../defaults/webhooklog.default';
20
+ import { EventEmitter2, OnEvent } from '@nestjs/event-emitter';
21
+
22
+ @Injectable()
23
+ export class WebhooklogProcessor extends SimpleAppService<Webhooklog> {
24
+ protected documentIdentityCode = '_id';
25
+ protected documentIdentityLabel = '';
26
+
27
+ protected foreignkeys = {};
28
+ constructor(mydoc: Model<Webhooklog>) {
29
+ super('WEBHOOKLOG', 'webhooklog', mydoc, IsolationType.branch);
30
+ this.setSchema(WebhooklogJsonSchema);
31
+ this.setData(DefaultWebhooklog(crypto.randomUUID()));
32
+ }
33
+
34
+ reCalculateValue(data: Webhooklog) {
35
+ //console.log('trigger new recalculate')
36
+ const $data = data;
37
+ }
38
+ @OnEvent('webhooklog.add')
39
+ addLog(appuser: UserContext, whlog: Webhooklog) {
40
+ const newdoc = new this.doc(whlog);
41
+ newdoc.save();
42
+ }
43
+
44
+ /***************************** additional execute *****************************************/
45
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * This file was automatically generated by simpleapp generator. It is changable
3
+ * --remove-this-line-to-prevent-override--
4
+ * last change 2024-02-23
5
+ * Author: Ks Tan
6
+ */
7
+
8
+ import { InjectModel } from '@nestjs/mongoose';
9
+ import { Model } from 'mongoose';
10
+ import { Injectable } from '@nestjs/common';
11
+ import { UserContext } from '../generate/commons/user.context';
12
+ import { WebhookProcessor } from '../generate/processors/webhook.processor';
13
+ //import { Webhook,WebhookHooks} from '../generate/types';
14
+ import * as types from '../generate/types';
15
+ import { WebhooklogService } from './webhooklog.service';
16
+ export { Webhook } from '../generate/types';
17
+
18
+ @Injectable()
19
+ export class WebhookService extends WebhookProcessor {
20
+ //protected hooks: types.WebhookHooks = {}
21
+ constructor(
22
+ @InjectModel('Webhook') mydoc: Model<types.Webhook>,
23
+ private webhooklogService: WebhooklogService,
24
+ ) {
25
+ super(mydoc);
26
+ }
27
+
28
+ /***************************** begin x-document-api definitions *****************************************/
29
+
30
+
31
+ async runGetHistories(appuser: UserContext, id: string) {
32
+ const results = await this.webhooklogService.search(appuser, { webHookId: id });
33
+ return results;
34
+ }
35
+
36
+ /***************************** end x-document-api definitions *****************************************/
37
+ }
@@ -5,33 +5,40 @@
5
5
  * Author: Ks Tan
6
6
  */
7
7
 
8
- import { Webhook } from "../generate/types";
9
- const branch_hooks:Webhook[] = []
8
+ import { Webhook } from '../generate/types';
9
+ const branch_hooks: Webhook[] = [];
10
10
 
11
- branch_hooks.push({
12
- "_id": "branch.update",
13
- "title": "branch_update",
14
- "url": "https://localhost:8080",
15
- "requestMethod": "post",
16
- "authentication": "none",
17
- "description": "aa",
18
- "body": '{ "id":"{{_id}}", "code":"{{branchCode}}","name":"{{branchName}}" }',
19
- "active": false,
20
- "resourceName": "branch",
21
- "eventType": "update",
22
- "jobType": "realtime",
23
- "retryAttemps": 2,
24
- "basicAuth": {
25
- "user": "",
26
- "password": ""
11
+
12
+
13
+ branch_hooks.push({
14
+ _id: 'branch.create.welcome-msg',
15
+ title: 'branch first send well come message',
16
+ url: 'https://mywebhook.app.com/init-new-branch',
17
+ requestMethod: 'post',
18
+ authentication: 'none',
19
+ description: '',
20
+ body: `{
21
+ "email":"{{email}}",
22
+ "name":"{{$fullName}}",
23
+ "centerName":"{{branchName}}",
24
+ "centerUrl":"https://myurl.com"
25
+ }`,
26
+ active: false,
27
+ resourceName: 'branch',
28
+ eventType: 'update',
29
+ // jobType: 'roll-back-when-failed',
30
+ jobType: 'realtime',
31
+ retryAttemps: 2,
32
+ basicAuth: {
33
+ user: '',
34
+ password: '',
27
35
  },
28
- "headers": [
36
+ headers: [
29
37
  {
30
- "name": "token",
31
- "value": "{{access_token}}"
32
- }
33
- ]
34
- })
35
-
38
+ name: 'x-api-key',
39
+ value: 'xxxxxxxxxx',
40
+ },
41
+ ],
42
+ });
36
43
 
37
- export default branch_hooks
44
+ export default branch_hooks;
@@ -1,224 +0,0 @@
1
- /**
2
- * This file was automatically generated by simpleapp generator. Every
3
- * MODIFICATION OVERRIDE BY GENERATEOR
4
- * last change 2024-07-10
5
- * Author: Ks Tan
6
- * Last Modified By: Yong Xiang
7
- */
8
- import { UserContext } from '../commons/user.context';
9
- import * as sharelibs from '../sharelibs';
10
- import { Injectable, InternalServerErrorException, } from '@nestjs/common';
11
- import { InjectModel } from '@nestjs/mongoose';
12
- import jsonpath from 'jsonpath';
13
- import { Model } from 'mongoose';
14
- import { WebhookJsonSchema } from '../jsonschemas/webhook.jsonschema';
15
- import { SimpleAppService } from './simpleapp.processor';
16
- import * as types from '../types';
17
- import { DocNumberFormatGenerator } from '../commons/docnogenerator.service';
18
- import {
19
- WebhookBasicAuth,
20
- WebhookHeaders,
21
- Webhook,
22
- } from '../types/webhook.type';
23
- import {
24
- DefaultWebhookBasicAuth,
25
- DefaultWebhookHeaders,
26
- DefaultWebhook,
27
- } from '../defaults/webhook.default';
28
-
29
- @Injectable()
30
- export class WebhookProcessor extends SimpleAppService<Webhook> {
31
- protected documentIdentityCode = 'title';
32
- protected documentIdentityLabel = 'title';
33
- private webhookApiKey = process.env.WEBHOOK_SERVER_APIKEY
34
- private webhookAppId=process.env.WEBHOOK_SERVER_APP_ID
35
- private webhookurl = process.env.WEBHOOK_SERVER_URL;
36
- private webhookprefix = process.env.PROJECT_CODE+'.'
37
- private webhooksubscribtionurl = `${process.env.WEBHOOK_SERVER_URL}/subscriptions/`;
38
-
39
- protected hooks: types.WebhookHooks = {
40
- beforeCreate: async (appuser: UserContext, data: types.Webhook) =>
41
- this.beforeCreate(appuser, data),
42
- beforeUpdate: async (
43
- appuser: UserContext,
44
- id: string,
45
- prevdata: types.Webhook,
46
- newdata: types.Webhook,
47
- ) => this.beforeUpdate(appuser, id, prevdata, newdata),
48
- afterDelete: async (
49
- appuser: UserContext,
50
- result: types.DeleteResultType<types.Webhook>,
51
- id: string,
52
- ) => this.afterDelete(appuser, result, id),
53
- };
54
-
55
-
56
- protected foreignkeys = {};
57
- constructor(mydoc: Model<Webhook>) {
58
- super('WEBHOOK', 'webhook', mydoc, types.IsolationType.tenant);
59
- this.setSchema(WebhookJsonSchema);
60
- this.setData(DefaultWebhook(crypto.randomUUID()));
61
- }
62
-
63
- reCalculateValue(data: Webhook) {
64
- //console.log('trigger new recalculate')
65
- const $data = data;
66
- }
67
-
68
- async beforeCreate(appuser: UserContext, data: types.Webhook) {
69
- const createResult = await this.addRemoteWebhook(appuser, data);
70
- if (!createResult['subscription_id'])
71
- throw new InternalServerErrorException(
72
- 'syncronize webhook server failed',
73
- );
74
- data.serverSubscriptionId = createResult.subscription_id;
75
- data.serverSubscriptionSecret = createResult.secret;
76
- // throw new BadRequestException("fail purposely")
77
- }
78
-
79
- async beforeUpdate(
80
- appuser: UserContext,
81
- id: string,
82
- prevdata: types.Webhook,
83
- newdata: types.Webhook,
84
- ) {
85
-
86
- if(!prevdata.serverSubscriptionId){
87
- const createResult = await this.addRemoteWebhook(appuser, newdata);
88
- if (!createResult['subscription_id'])
89
- throw new InternalServerErrorException(
90
- 'syncronize webhook server failed',
91
- );
92
- newdata.serverSubscriptionId = createResult.subscription_id;
93
- newdata.serverSubscriptionSecret = createResult.secret;
94
- }else{
95
- await this.updateRemoteWebhook(appuser,newdata)
96
- }
97
- }
98
-
99
- async afterDelete(
100
- appuser: UserContext,
101
- result: types.DeleteResultType<types.Webhook>,
102
- id: string,
103
- ) {
104
- await this.removeRemoteWebhook(appuser,result,id)
105
- }
106
-
107
- async removeRemoteWebhook(
108
- appuser: UserContext,
109
- result: types.DeleteResultType<types.Webhook>,
110
- id: string,
111
- ){
112
- const options = {
113
- method: 'DELETE',
114
- headers: {Authorization: this.webhookApiKey}
115
- };
116
-
117
-
118
- const subscriptionId=result.data.serverSubscriptionId
119
- if(!subscriptionId)return
120
-
121
- try{
122
- const res = await fetch(
123
- `${this.webhooksubscribtionurl}/${subscriptionId}?application_id=${this.webhookAppId}`,
124
- options)
125
- }catch(e){
126
- throw new InternalServerErrorException(e)
127
- }
128
-
129
- }
130
- async addRemoteWebhook(appuser: UserContext, data: types.Webhook) {
131
- const headers = {};
132
- data.headers.forEach((h) => {
133
- headers[h.name] = h.value;
134
- });
135
-
136
- const options = {
137
- method: 'POST',
138
- headers: {
139
- Authorization: this.webhookApiKey,
140
- accept: 'application/json',
141
- 'content-type': 'application/json',
142
- },
143
- body: JSON.stringify({
144
- application_id: this.webhookAppId,
145
- description: data.title,
146
- metadata: {
147
- tenantId: data.tenantId.toString(),
148
- creator: appuser.getUname(),
149
- },
150
- is_enabled: data.active,
151
- event_types: data.eventTypes.map(
152
- (item) => this.webhookprefix + item,
153
- ),
154
- label_key: 'tenantId',
155
- label_value: data.tenantId.toString(),
156
- target: {
157
- headers: headers,
158
- type: 'http',
159
- method: data.requestMethod.toUpperCase(),
160
- url: data.url,
161
- },
162
- }),
163
- };
164
- try {
165
- const res = await fetch(this.webhooksubscribtionurl, options);
166
- return await res.json();
167
- if (res.status >= 300) {
168
- this.logger.error(res.statusText, 'create webhook failed');
169
- throw new InternalServerErrorException('create webhook failed');
170
- }
171
- } catch (e) {
172
- throw new InternalServerErrorException(e);
173
- }
174
- }
175
-
176
- async updateRemoteWebhook(appuser: UserContext, data: types.Webhook) {
177
- const headers = {};
178
- data.headers.forEach((h) => {
179
- headers[h.name] = h.value;
180
- });
181
-
182
- const options = {
183
- method: 'PUT',
184
- headers: {
185
- Authorization: this.webhookApiKey,
186
- accept: 'application/json',
187
- 'content-type': 'application/json',
188
- },
189
- body: JSON.stringify({
190
- application_id: this.webhookAppId,
191
- description: data.title,
192
- metadata: {
193
- tenantId: data.tenantId.toString(),
194
- creator: appuser.getUname(),
195
- },
196
- is_enabled: data.active,
197
- event_types: data.eventTypes.map(
198
- (item) => this.webhookprefix + item,
199
- ),
200
- label_key: 'tenantId',
201
- label_value: data.tenantId.toString(),
202
- target: {
203
- headers: headers,
204
- type: 'http',
205
- method: data.requestMethod.toUpperCase(),
206
- url: data.url,
207
- },
208
- }),
209
- };
210
- try {
211
- const subscriptionId = data.serverSubscriptionId
212
- const res = await fetch(`${this.webhooksubscribtionurl}/${subscriptionId}`, options);
213
- return await res.json();
214
- if (res.status >= 300) {
215
- this.logger.error(res.statusText, 'updateRemoteWebhook webhook failed');
216
- throw new InternalServerErrorException('update webhook failed');
217
- }
218
- } catch (e) {
219
- throw new InternalServerErrorException(e);
220
- }
221
- }
222
-
223
- /***************************** additional execute *****************************************/
224
- }