@simitgroup/simpleapp-generator 1.6.6-q-alpha → 1.6.6-s-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.
Files changed (66) hide show
  1. package/ReleaseNote.md +6 -0
  2. package/dist/buildinschemas/index.d.ts +1 -0
  3. package/dist/buildinschemas/index.d.ts.map +1 -1
  4. package/dist/buildinschemas/index.js +3 -1
  5. package/dist/buildinschemas/index.js.map +1 -1
  6. package/dist/buildinschemas/message.d.ts +3 -0
  7. package/dist/buildinschemas/message.d.ts.map +1 -0
  8. package/dist/buildinschemas/message.js +34 -0
  9. package/dist/buildinschemas/message.js.map +1 -0
  10. package/dist/buildinschemas/webhook.d.ts.map +1 -1
  11. package/dist/buildinschemas/webhook.js +124 -53
  12. package/dist/buildinschemas/webhook.js.map +1 -1
  13. package/dist/buildinschemas/webhookhistory.d.ts +3 -0
  14. package/dist/buildinschemas/webhookhistory.d.ts.map +1 -0
  15. package/dist/buildinschemas/webhookhistory.js +44 -0
  16. package/dist/buildinschemas/webhookhistory.js.map +1 -0
  17. package/dist/buildinschemas/webhooklog.d.ts +3 -0
  18. package/dist/buildinschemas/webhooklog.d.ts.map +1 -0
  19. package/dist/buildinschemas/webhooklog.js +77 -0
  20. package/dist/buildinschemas/webhooklog.js.map +1 -0
  21. package/dist/createproject.js +138 -0
  22. package/dist/createproject.js.map +1 -0
  23. package/dist/framework.js +3 -3
  24. package/dist/framework.js.map +1 -1
  25. package/dist/generate-allow-changebackend.js +305 -0
  26. package/dist/generate-allow-changebackend.js.map +1 -0
  27. package/dist/generate.js +2 -2
  28. package/dist/generate.js.map +1 -1
  29. package/dist/index2.js +118 -0
  30. package/dist/index2.js.map +1 -0
  31. package/dist/installdependency.js +20 -0
  32. package/dist/installdependency.js.map +1 -0
  33. package/dist/installnest.js +2 -0
  34. package/dist/installnest.js.map +1 -0
  35. package/dist/installnuxt.js +2 -0
  36. package/dist/installnuxt.js.map +1 -0
  37. package/dist/processors/groupsbuilder.js +2 -0
  38. package/dist/processors/groupsbuilder.js.map +1 -0
  39. package/dist/schematype/baseschema.js +25 -0
  40. package/dist/schematype/baseschema.js.map +1 -0
  41. package/dist/schematype/default.js +2 -0
  42. package/dist/schematype/default.js.map +1 -0
  43. package/dist/schematype/index.js +12 -0
  44. package/dist/schematype/index.js.map +1 -0
  45. package/dist/schematype/primarymasterdata.js +38 -0
  46. package/dist/schematype/primarymasterdata.js.map +1 -0
  47. package/dist/schematype/simple.js +24 -0
  48. package/dist/schematype/simple.js.map +1 -0
  49. package/dist/schematype/simplemasterdata.js +31 -0
  50. package/dist/schematype/simplemasterdata.js.map +1 -0
  51. package/dist/schematype/transaction.js +74 -0
  52. package/dist/schematype/transaction.js.map +1 -0
  53. package/package.json +1 -1
  54. package/src/buildinschemas/index.ts +1 -0
  55. package/src/buildinschemas/webhook.ts +126 -55
  56. package/src/buildinschemas/webhooklog.ts +75 -0
  57. package/src/framework.ts +4 -4
  58. package/src/generate.ts +2 -2
  59. package/templates/nest/src/simpleapp/generate/commons/middlewares/tenant.middleware.ts.eta +4 -2
  60. package/templates/nest/src/simpleapp/generate/commons/runwebhook.service.ts.eta +143 -168
  61. package/templates/nest/src/simpleapp/generate/commons/user.context.ts.eta +22 -13
  62. package/templates/nest/src/simpleapp/generate/processors/simpleapp.processor.ts.eta +22 -16
  63. package/templates/nest/src/simpleapp/webhooks/branch.ts._eta +37 -0
  64. package/templates/nest/src/simpleapp/webhooks/index.ts._eta +21 -0
  65. package/templates/nuxt/plugins/20.simpleapp-userstore.ts.eta +341 -316
  66. /package/templates/nest/src/simpleapp/generate/processors/{webhook.processor.ts.eta → webhook.processor.ts.etaxxxx} +0 -0
@@ -13,6 +13,7 @@ import { Model } from 'mongoose';
13
13
  import { Permission } from '../../types/perm.type';
14
14
  import { User } from '../../types/user.type';
15
15
  import { Appintegration } from '../../types/appintegration.type';
16
+ import { Webhook } from '../../types/Webhook.type';
16
17
  import { UserContext } from '../user.context';
17
18
 
18
19
  @Injectable()
@@ -27,6 +28,7 @@ export class TenantMiddleware implements NestMiddleware {
27
28
  @InjectModel('User') private readonly userModel: Model<User>,
28
29
  @InjectModel('Permission') private readonly permModel: Model<Permission>,
29
30
  @InjectModel('Appintegration') private readonly appModel: Model<Appintegration>,
31
+ @InjectModel('Webhook') private readonly webhookModel: Model<Webhook>,
30
32
  ) {}
31
33
 
32
34
  requireXOrg(baseurl: string): boolean {
@@ -53,7 +55,7 @@ export class TenantMiddleware implements NestMiddleware {
53
55
 
54
56
  if (req.baseUrl == '/graphql') {
55
57
  if (tokenStr) {
56
- await user.setCurrentUserInfo(tokenStr, xOrg);
58
+ await user.setCurrentUserInfo(tokenStr, xOrg,this.webhookModel);
57
59
  }
58
60
  req['sessionuser'] = user;
59
61
  next();
@@ -88,7 +90,7 @@ export class TenantMiddleware implements NestMiddleware {
88
90
  }
89
91
 
90
92
  try {
91
- await user.setCurrentUserInfo(tokenStr, xOrg);
93
+ await user.setCurrentUserInfo(tokenStr, xOrg,this.webhookModel);
92
94
  if (user.getId() == '' && this.requireXOrg(req.baseUrl)) {
93
95
  this.logger.log('Access deny for user:', req.baseUrl);
94
96
  return res.status(401).send('Access deny for user');
@@ -4,192 +4,167 @@
4
4
  * last change 2024-03-17
5
5
  * Author: Ks Tan
6
6
  */
7
- import {
8
- BadRequestException,
9
- Injectable,
10
- InternalServerErrorException,
11
- Logger,
12
- NotFoundException,
13
- } from '@nestjs/common';
7
+ import { BadRequestException, Injectable,Inject, InternalServerErrorException, Logger, NotFoundException } from '@nestjs/common';
14
8
  import { EventEmitter2, OnEvent } from '@nestjs/event-emitter';
15
9
  import { UserContext } from './user.context';
16
- import {
17
- Webhook,
18
- WebhookService,
19
- } from 'src/simpleapp/services/webhook.service';
10
+ import { Webhook,Webhooklog } from '../types';
20
11
  import { alldocuments } from 'src/simpleapp/generate/commons/dicts/documents';
21
12
 
22
13
  @Injectable()
23
14
  export class RunWebhookService {
24
- private webhookApiKey = process.env.WEBHOOK_SERVER_APIKEY;
25
- private webhookAppId = process.env.WEBHOOK_SERVER_APP_ID;
26
- private webhookurl = process.env.WEBHOOK_SERVER_URL;
27
- private webhookprefix = process.env.PROJECT_CODE + '.';
28
- private webhookeventurl = `${process.env.WEBHOOK_SERVER_URL}/event/`;
29
- private webhookeventtypeurl = `${process.env.WEBHOOK_SERVER_URL}/event_types/`;
30
- private webhooksync: boolean = process.env.WEBHOOKER_SYNC_EVENTTYPE == 'true';
31
-
32
- public constructor(private webhookService: WebhookService) {
33
- if (this.webhooksync) this.syncEventTypes();
15
+ @Inject(EventEmitter2)
16
+ protected eventEmitter: EventEmitter2;
17
+
18
+ protected logger = new Logger();
19
+ protected maxRetries = 5
20
+ public constructor() {}
21
+
22
+
23
+
24
+ /**
25
+ * trigger
26
+ */
27
+ async run(appuser: UserContext, documentName: string, actionName: string, data: any) {
28
+ return await this.runRealtimeWebHook(appuser,documentName,actionName,data)
34
29
  }
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
+ */
39
+ async runRealtimeWebHook(appuser: UserContext, documentName: string, actionName: string, data: any) {
40
+ this.logger.debug(`Run webhook ${documentName}, ${actionName}`);
41
+ // console.log(`Run webhook ${documentName}, ${actionName}`);
42
+
43
+
44
+ const webhooks = appuser.getWebHooks().filter(wh=>
45
+ wh.resourceName==documentName && wh.eventType==actionName
46
+ )
47
+ // 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
+
52
+ const webhook = webhooks[whNo]
53
+ const reqMethod = webhook.requestMethod
54
+ this.logger.verbose(webhook)
55
+ const headers = {};
56
+
57
+ if (Array.isArray(webhook.headers)) {
58
+ webhook.headers.forEach((h) => {
59
+ h.value = h.value.replace('{{access_token}}',appuser.getUserToken())
60
+ headers[h.name] = h.value;
61
+ });
62
+ }
63
+ headers['accept'] = 'application/json';
64
+ 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');
35
71
 
36
- @OnEvent('webhook')
37
- async loadWebhook(
38
- appuser: UserContext,
39
- documentName: string,
40
- actionName: string,
41
- data?: any,
42
- ) {
43
- //no webhook server implemented
44
- if (!this.webhookApiKey) return true;
45
-
46
- const filter = {
47
- eventTypes: documentName + '.' + actionName,
48
- active: true,
49
- };
50
- // console.log('Load webhook', documentName, actionName, filter);
51
- const webhooks = await this.webhookService.search(appuser, filter);
52
- // console.log('Loaded webhook', webhooks);
53
- if (webhooks.length == 0) return;
54
-
55
- for (let i = 0; i < webhooks.length; i++) {
56
- const webhook = webhooks[i];
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 = {
78
+ method: reqMethod.toUpperCase(),
79
+ headers: headers,
80
+
81
+ };
57
82
  try {
58
- const res = await this.runWebHook(
59
- appuser,
60
- webhook,
61
- documentName,
62
- actionName,
63
- data,
64
- );
83
+ if(['POST','PUT','PATCH'].includes(options.method)){
84
+ options.body= this.prepareBody(webhook,data)
85
+ }
86
+
87
+
88
+
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
+
96
+
97
+
98
+ if (statusCode >= 200 && statusCode <= 300) {
99
+ //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)
102
+ 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)
116
+ }
117
+
118
+ }
119
+
120
+ // const body = req.body;
65
121
  } catch (e) {
66
- return e;
122
+ throw new InternalServerErrorException(e);
67
123
  }
124
+
68
125
  }
126
+
127
+ return true
69
128
  }
70
129
 
71
- async runWebHook(
72
- appuser: UserContext,
73
- webhook: Webhook,
74
- documentName: string,
75
- actionName: string,
76
- data: any,
77
- ) {
78
- const headers = {};
79
-
80
- // console.log('Run webhook ', documentName, actionName);
81
- if (Array.isArray(webhook.headers)) {
82
- webhook.headers.forEach((h) => {
83
- headers[h.name] = h.value;
84
- });
85
- }
86
- headers['accept'] = 'application/json';
87
- headers['content-type'] = 'application/json';
88
- headers['Authorization'] = this.webhookApiKey;
89
- const eventname = `${this.webhookprefix}${documentName}.${actionName}`;
90
- const options = {
91
- method: webhook.requestMethod.toUpperCase(),
92
- headers: headers,
93
- body: JSON.stringify({
94
- labels: {
95
- tenantId: appuser.getTenantId().toString(),
96
- },
97
- metadata: {
98
- src: process.env.PROJECT_NAME,
99
- user: appuser.getFullname(),
100
- },
101
- application_id: this.webhookAppId,
102
- event_type: eventname,
103
- event_id: crypto.randomUUID(),
104
- occurred_at: new Date().toISOString(),
105
- payload: JSON.stringify(data),
106
- payload_content_type: 'application/json',
107
- }),
108
- };
109
- try {
110
- // console.log('webhook request ', this.webhookeventurl, options);
111
- const req = await fetch(this.webhookeventurl, options);
112
- const statusCode = req.status;
113
- if (statusCode >= 300) {
114
- throw new InternalServerErrorException(
115
- `create event ${eventname} failed to webhook server`,
116
- );
117
- }
118
130
 
119
- // const body = req.body;
120
- } catch (e) {
121
- return e;
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)
122
137
  }
123
- }
138
+ else if(status=='success')
139
+ this.logger.debug(msg)
140
+ else
141
+ this.logger.error (msg)
124
142
 
125
- async syncEventTypes() {
126
- const options = {
127
- method: 'GET',
128
- headers: {
129
- accept: 'application/json',
130
- Authorization: this.webhookApiKey,
131
- },
132
- };
133
- // {
134
- // "service_name": "billing",
135
- // "resource_type_name": "invoice",
136
- // "verb_name": "documentno",
137
- // "event_type_name": "billing.invoice.documentno"
138
- // },
139
- try {
140
- const res = await fetch(
141
- `${this.webhookeventtypeurl}?application_id=${this.webhookAppId}`,
142
- options,
143
- );
144
-
145
- const locallist = this.getSchemaEventTypes();
146
- const eventlist = (await res.json()).map((item) => item.event_type_name);
147
-
148
- for (let i = 0; i < locallist.length; i++) {
149
- const item = locallist[i];
150
- if (!eventlist.includes(item)) {
151
- //create remote event type
152
- await this.createEventType(item);
153
- }
154
- }
155
- } catch (e) {
156
- throw new InternalServerErrorException(e);
143
+ let body = JSON.stringify(options,null,4)
144
+
145
+ const whlog: Webhooklog = {
146
+ title: `${webhook.requestMethod} ${webhook.url}`,
147
+ resource: documentName,
148
+ actionName: actionName,
149
+ status: status,
150
+ statusCode: statusCode,
151
+ body: body,
152
+ msg:msg
157
153
  }
158
- }
159
154
 
160
- async createEventType(eventname: string) {
161
- const para = eventname.split('.');
162
- const options = {
163
- method: 'POST',
164
- headers: {
165
- accept: 'application/json',
166
- 'content-type': 'application/json',
167
- Authorization: this.webhookApiKey,
168
- },
169
- body: JSON.stringify({
170
- application_id: this.webhookAppId,
171
- resource_type: para[0],
172
- service: para[1],
173
- verb: para[2],
174
- }),
175
- };
176
-
177
- await fetch(this.webhookeventtypeurl, options);
178
- // .then(response => response.json())
179
- // .then(response => console.log(response))
180
- // .catch(err => console.error(err));
181
- }
182
- getSchemaEventTypes() {
183
- const alleventtypes: string[] = [];
184
- alldocuments
185
- .filter((item) => Array.isArray(item.webhook))
186
- .forEach((item) => {
187
- item.webhook.forEach((h) => {
188
- alleventtypes.push(
189
- `${this.webhookprefix}${item.docName.toLowerCase()}.${h}`,
190
- );
191
- });
192
- });
193
- return alleventtypes;
155
+ this.eventEmitter.emit('webhooklog.add', appuser,whlog);
194
156
  }
157
+ prepareBody(webhook:Webhook,data:any){
158
+ const cleandata = JSON.parse(JSON.stringify(data))
159
+
160
+ if(webhook.body?.trim()=='*'){
161
+ return JSON.stringify(cleandata)
162
+ }
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
+
195
170
  }
@@ -6,15 +6,18 @@
6
6
  * 2.
7
7
  */
8
8
  import Base64URL from '@darkwolf/base64url';
9
+ import { InjectModel } from '@nestjs/mongoose';
9
10
  import { BadRequestException, ForbiddenException, Injectable, Logger, Scope } from '@nestjs/common';
10
11
  import * as jwt from 'jsonwebtoken';
11
12
  import { ClientSession, Model, PipelineStage } from 'mongoose';
12
- import { Branch, Organization, Permission, Tenant, TenantClientSetting, User, Appintegration } from 'src/simpleapp/generate/types';
13
+ import { Branch, Organization, Permission, Tenant, TenantClientSetting, User, Appintegration, Webhook } from 'src/simpleapp/generate/types';
13
14
  import { ProfileUserBranch, ProfileUserInvites } from '../../profile/profile.types';
14
15
  import { ModifiedRecords } from '../types';
15
16
  import { Role } from './roles/roles.enum';
17
+ import systemWebHooks from '../../webhooks';
16
18
  import * as rolegroups from './roles/roles.group';
17
19
 
20
+
18
21
  @Injectable({ scope: Scope.REQUEST })
19
22
  export class UserContext {
20
23
  protected sessionId: string = crypto.randomUUID();
@@ -89,6 +92,7 @@ export class UserContext {
89
92
 
90
93
  protected package: string = '';
91
94
 
95
+ protected webhooks: Webhook[] = systemWebHooks
92
96
  protected clientSetting: TenantClientSetting = {
93
97
  auditTrail: false,
94
98
  support: false,
@@ -97,7 +101,7 @@ export class UserContext {
97
101
  };
98
102
 
99
103
  private dbsession: ClientSession;
100
-
104
+
101
105
  protected modifiedRecords: ModifiedRecords = {
102
106
  createds: {},
103
107
  updateds: {},
@@ -110,7 +114,7 @@ export class UserContext {
110
114
  } = { simbiz6: false, einvoice: false };
111
115
 
112
116
  constructor(
113
- private readonly userModel: Model<User>,
117
+ private readonly userModel: Model<User>,
114
118
  private readonly permModel: Model<Permission>,
115
119
  private readonly appModel: Model<Appintegration>,
116
120
  ) {}
@@ -202,9 +206,14 @@ export class UserContext {
202
206
  return data;
203
207
  };
204
208
 
205
- setCurrentUserInfo = async (tokenstr: string, xOrg: string) => {
209
+
210
+ setCurrentUserInfo = async (tokenstr: string, xOrg: string,webhookModel:Model<Webhook>) => {
206
211
  this.setXOrg(xOrg);
207
- await this.setUserToken(tokenstr);
212
+ await this.setUserToken(tokenstr);
213
+ const wh = await webhookModel.find({branchId:this.getBranchId(),active:true})
214
+
215
+ if(Array.isArray(wh) && wh.length>0)
216
+ this.webhooks = this.webhooks.concat(wh)
208
217
  };
209
218
 
210
219
  /**
@@ -258,6 +267,7 @@ export class UserContext {
258
267
  as: 'currentTenant',
259
268
  },
260
269
  },
270
+
261
271
  {
262
272
  $unwind: '$currentTenant',
263
273
  },
@@ -391,7 +401,8 @@ export class UserContext {
391
401
  orgId: this.orgId,
392
402
  };
393
403
  };
394
-
404
+ getWebHooks = ()=> this.webhooks
405
+
395
406
  getWorkflowTaskFilter() {
396
407
  return {
397
408
  'data.tenantId': this.tenantId,
@@ -720,7 +731,6 @@ export class UserContext {
720
731
  return results;
721
732
  }
722
733
 
723
-
724
734
  setAsStaticUser = (uid: string, uname: string, name: string, email: string, xorg: string) => {
725
735
  // Define token info
726
736
  this.token = '';
@@ -757,13 +767,12 @@ export class UserContext {
757
767
  const appintegration = await this.appModel.aggregate(extension);
758
768
  if (appintegration && appintegration.length > 0) {
759
769
  appintegration.forEach((item) => {
760
- if (item.appId === 'simbiz6') this.appintegration.simbiz6 = true;
761
- if (item.appId === 'einvoice') this.appintegration.einvoice = true;
762
- });
770
+ if (item.appId === 'simbiz6') this.appintegration.simbiz6 = true;
771
+ if (item.appId === 'einvoice') this.appintegration.einvoice = true;
772
+ });
773
+ }
774
+ return this.appintegration;
763
775
  }
764
- return this.appintegration;
765
-
766
- }
767
776
  /**
768
777
  * Define additional properties from user into moreProps
769
778
  */
@@ -35,6 +35,7 @@ import { UserContext } from '../commons/user.context';
35
35
  import { CloudApiService } from 'src/cloudapi/cloudapi.service';
36
36
  import { PrintApiService } from 'src/printapi/printapi.service';
37
37
  import { DocNumberFormatGenerator } from '../commons/docnogenerator.service';
38
+ import { RunWebhookService } from '../commons/runwebhook.service';
38
39
  import {
39
40
  IsolationType,
40
41
  DefaultHooks,
@@ -54,6 +55,8 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
54
55
  protected cloudapi: CloudApiService;
55
56
  @Inject(PrintApiService)
56
57
  protected printapi: PrintApiService;
58
+ @Inject(RunWebhookService)
59
+ protected runWebHook:RunWebhookService;
57
60
  protected hooks: DefaultHooks<T> = {};
58
61
  protected logger = new Logger();
59
62
  protected strictIsolation = true;
@@ -490,7 +493,7 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
490
493
  try {
491
494
  if (this.hooks.afterCreate)
492
495
  await this.hooks.afterCreate(appuser, result);
493
- this.callWebhook(appuser, 'create', result);
496
+ await this.callWebhook(appuser, 'create', result);
494
497
 
495
498
  // return result as T;
496
499
  } catch (err) {
@@ -608,7 +611,7 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
608
611
 
609
612
  try {
610
613
  if (this.hooks.afterCreate) await this.hooks.afterCreate(appuser, result);
611
- this.callWebhook(appuser, 'create', result);
614
+ await this.callWebhook(appuser, 'create', result);
612
615
  return result as T;
613
616
  } catch (err) {
614
617
  throw new InternalServerErrorException(
@@ -690,7 +693,7 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
690
693
 
691
694
  try {
692
695
  if (this.hooks.afterCreate) await this.hooks.afterCreate(appuser, result);
693
- this.callWebhook(appuser, 'create', result);
696
+ await this.callWebhook(appuser, 'create', result);
694
697
  return result as T;
695
698
  } catch (err) {
696
699
  throw new InternalServerErrorException(
@@ -863,7 +866,7 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
863
866
  if (this.hooks.afterDelete)
864
867
  await this.hooks.afterDelete(appuser, deleteresult, id);
865
868
  //this.doc.findByIdAndDelete(id);
866
- this.callWebhook(appuser, 'delete', deletedata);
869
+ await this.callWebhook(appuser, 'delete', deletedata);
867
870
  return deleteresult;
868
871
  } else {
869
872
  this.logger.debug('reject query', dependency);
@@ -956,7 +959,7 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
956
959
  appuser.addUpdatedRecordId(this.documentName, data._id);
957
960
  if (this.hooks.afterUpdate)
958
961
  await this.hooks.afterUpdate(appuser, id, existingdata, result);
959
- this.callWebhook(appuser, 'update', result);
962
+ await this.callWebhook(appuser, 'update', result);
960
963
  return result; // await this.findById(appuser, id);
961
964
  } catch (err) {
962
965
  this.logger.error(err);
@@ -1033,7 +1036,7 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
1033
1036
  appuser.addUpdatedRecordId(this.documentName, data._id);
1034
1037
  if (this.hooks.afterUpdate)
1035
1038
  await this.hooks.afterUpdate(appuser, id, existingdata, result);
1036
- this.callWebhook(appuser, 'update', result);
1039
+ await this.callWebhook(appuser, 'update', result);
1037
1040
  return result; // await this.findById(appuser, id);
1038
1041
  } catch (err) {
1039
1042
  this.logger.error(err);
@@ -1102,7 +1105,7 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
1102
1105
 
1103
1106
  if (this.hooks.afterUpdate)
1104
1107
  await this.hooks.afterUpdate(appuser, id, existingdata, result);
1105
- this.callWebhook(appuser, 'update', result);
1108
+ await this.callWebhook(appuser, 'update', result);
1106
1109
  return result; //await this.findById(appuser, id);
1107
1110
  } catch (err) {
1108
1111
  throw new InternalServerErrorException(err.message);
@@ -1224,7 +1227,7 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
1224
1227
  data,
1225
1228
  );
1226
1229
 
1227
- this.callWebhook(appuser, docstatus, finaldata);
1230
+ await this.callWebhook(appuser, docstatus, finaldata);
1228
1231
  return updateresult;
1229
1232
  }
1230
1233
  }
@@ -1482,13 +1485,16 @@ export class SimpleAppService<T extends { _id?: string; __v?: number }> {
1482
1485
  return pipelines;
1483
1486
  }
1484
1487
 
1485
- callWebhook(appuser: UserContext, actionName: string, data: any) {
1486
- this.eventEmitter.emit(
1487
- 'webhook',
1488
- appuser,
1489
- this.documentName,
1490
- actionName,
1491
- data,
1492
- );
1488
+
1489
+ //only realtime webhook supported at this moment
1490
+ async callWebhook(appuser: UserContext, actionName: string, data: any) {
1491
+ try{
1492
+ await this.runWebHook.run(appuser,this.documentName, actionName,data)
1493
+ }
1494
+ catch(e)
1495
+ {
1496
+ throw new InternalServerErrorException(e);
1497
+ }
1498
+
1493
1499
  }
1494
1500
  }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * This file was automatically generated by simpleapp generator. Every
3
+ * --remove-this-line-to-prevent-override--
4
+ * last change 2025-06-26
5
+ * Author: Ks Tan
6
+ */
7
+
8
+ import { Webhook } from "../generate/types";
9
+ const branch_hooks:Webhook[] = []
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": ""
27
+ },
28
+ "headers": [
29
+ {
30
+ "name": "token",
31
+ "value": "{{access_token}}"
32
+ }
33
+ ]
34
+ })
35
+
36
+
37
+ export default branch_hooks
@@ -0,0 +1,21 @@
1
+ /**
2
+ * This file was automatically generated by simpleapp generator. Every
3
+ * --remove-this-line-to-prevent-override--
4
+ * last change 2025-06-26
5
+ * Author: Ks Tan
6
+ */
7
+
8
+ import { Webhook } from "../generate/types";
9
+ import branch_hooks from './branch'
10
+
11
+ const systemWebHooks:Webhook[] = []
12
+ function addMore(hooks:Webhook[]){
13
+ hooks.forEach(h=>{
14
+ if(h.active) systemWebHooks.push(h)
15
+ })
16
+ }
17
+
18
+ addMore(branch_hooks)
19
+
20
+
21
+ export default systemWebHooks