@hed-hog/core 0.0.325 → 0.0.327

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 (100) hide show
  1. package/dist/core.module.d.ts.map +1 -1
  2. package/dist/core.module.js +3 -0
  3. package/dist/core.module.js.map +1 -1
  4. package/dist/index.d.ts +4 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +4 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/integration/services/outbox.processor.d.ts.map +1 -1
  9. package/dist/integration/services/outbox.processor.js +1 -0
  10. package/dist/integration/services/outbox.processor.js.map +1 -1
  11. package/dist/integration/types/event.types.d.ts +1 -0
  12. package/dist/integration/types/event.types.d.ts.map +1 -1
  13. package/dist/mail/mail.controller.d.ts +2 -0
  14. package/dist/mail/mail.controller.d.ts.map +1 -1
  15. package/dist/mail/mail.module.d.ts.map +1 -1
  16. package/dist/mail/mail.module.js +33 -53
  17. package/dist/mail/mail.module.js.map +1 -1
  18. package/dist/mail/mail.service.d.ts +5 -1
  19. package/dist/mail/mail.service.d.ts.map +1 -1
  20. package/dist/mail/mail.service.js +64 -84
  21. package/dist/mail/mail.service.js.map +1 -1
  22. package/dist/role/role.service.d.ts +3 -1
  23. package/dist/role/role.service.d.ts.map +1 -1
  24. package/dist/role/role.service.js +33 -5
  25. package/dist/role/role.service.js.map +1 -1
  26. package/dist/setting/setting.service.d.ts.map +1 -1
  27. package/dist/setting/setting.service.js +1 -0
  28. package/dist/setting/setting.service.js.map +1 -1
  29. package/dist/user/user.service.d.ts +3 -1
  30. package/dist/user/user.service.d.ts.map +1 -1
  31. package/dist/user/user.service.js +31 -4
  32. package/dist/user/user.service.js.map +1 -1
  33. package/dist/webhook-integration/event-webhook.controller.d.ts +29 -0
  34. package/dist/webhook-integration/event-webhook.controller.d.ts.map +1 -0
  35. package/dist/webhook-integration/event-webhook.controller.js +93 -0
  36. package/dist/webhook-integration/event-webhook.controller.js.map +1 -0
  37. package/dist/webhook-integration/event-webhook.service.d.ts +54 -0
  38. package/dist/webhook-integration/event-webhook.service.d.ts.map +1 -0
  39. package/dist/webhook-integration/event-webhook.service.js +334 -0
  40. package/dist/webhook-integration/event-webhook.service.js.map +1 -0
  41. package/dist/webhook-integration/integration-event-catalog.controller.d.ts +21 -0
  42. package/dist/webhook-integration/integration-event-catalog.controller.d.ts.map +1 -0
  43. package/dist/webhook-integration/integration-event-catalog.controller.js +91 -0
  44. package/dist/webhook-integration/integration-event-catalog.controller.js.map +1 -0
  45. package/dist/webhook-integration/integration-event-catalog.service.d.ts +26 -0
  46. package/dist/webhook-integration/integration-event-catalog.service.d.ts.map +1 -0
  47. package/dist/webhook-integration/integration-event-catalog.service.js +112 -0
  48. package/dist/webhook-integration/integration-event-catalog.service.js.map +1 -0
  49. package/dist/webhook-integration/webhook-integration.controller.d.ts +44 -0
  50. package/dist/webhook-integration/webhook-integration.controller.d.ts.map +1 -0
  51. package/dist/webhook-integration/webhook-integration.controller.js +181 -0
  52. package/dist/webhook-integration/webhook-integration.controller.js.map +1 -0
  53. package/dist/webhook-integration/webhook-integration.module.d.ts +3 -0
  54. package/dist/webhook-integration/webhook-integration.module.d.ts.map +1 -0
  55. package/dist/webhook-integration/webhook-integration.module.js +54 -0
  56. package/dist/webhook-integration/webhook-integration.module.js.map +1 -0
  57. package/dist/webhook-integration/webhook-integration.service.d.ts +73 -0
  58. package/dist/webhook-integration/webhook-integration.service.d.ts.map +1 -0
  59. package/dist/webhook-integration/webhook-integration.service.js +569 -0
  60. package/dist/webhook-integration/webhook-integration.service.js.map +1 -0
  61. package/dist/webhook-integration/webhook-utils.d.ts +7 -0
  62. package/dist/webhook-integration/webhook-utils.d.ts.map +1 -0
  63. package/dist/webhook-integration/webhook-utils.js +104 -0
  64. package/dist/webhook-integration/webhook-utils.js.map +1 -0
  65. package/hedhog/data/integration_event_catalog.yaml +118 -0
  66. package/hedhog/data/mail_profile.yaml +18 -0
  67. package/hedhog/data/menu.yaml +26 -12
  68. package/hedhog/data/route.yaml +152 -8
  69. package/hedhog/data/setting_group.yaml +7 -156
  70. package/hedhog/data/setting_subgroup.yaml +0 -32
  71. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +205 -0
  72. package/hedhog/frontend/app/integrations-webhooks/page.tsx.ejs +1835 -0
  73. package/hedhog/frontend/messages/en.json +2 -1
  74. package/hedhog/frontend/messages/pt.json +2 -1
  75. package/hedhog/table/event_webhook.yaml +55 -0
  76. package/hedhog/table/event_webhook_delivery_log.yaml +66 -0
  77. package/hedhog/table/event_webhook_event.yaml +26 -0
  78. package/hedhog/table/integration_event_catalog.yaml +41 -0
  79. package/hedhog/table/setting.yaml +1 -0
  80. package/hedhog/table/webhook_action.yaml +85 -0
  81. package/hedhog/table/webhook_call_log.yaml +46 -0
  82. package/hedhog/table/webhook_integration.yaml +43 -0
  83. package/package.json +3 -3
  84. package/src/core.module.ts +10 -7
  85. package/src/index.ts +10 -5
  86. package/src/integration/services/outbox.processor.ts +5 -4
  87. package/src/integration/types/event.types.ts +4 -3
  88. package/src/mail/mail.module.ts +36 -59
  89. package/src/mail/mail.service.ts +84 -89
  90. package/src/role/role.service.ts +41 -8
  91. package/src/setting/setting.service.ts +7 -6
  92. package/src/user/user.service.ts +34 -3
  93. package/src/webhook-integration/event-webhook.controller.ts +50 -0
  94. package/src/webhook-integration/event-webhook.service.ts +384 -0
  95. package/src/webhook-integration/integration-event-catalog.controller.ts +50 -0
  96. package/src/webhook-integration/integration-event-catalog.service.ts +117 -0
  97. package/src/webhook-integration/webhook-integration.controller.ts +103 -0
  98. package/src/webhook-integration/webhook-integration.module.ts +45 -0
  99. package/src/webhook-integration/webhook-integration.service.ts +735 -0
  100. package/src/webhook-integration/webhook-utils.ts +79 -0
@@ -0,0 +1,384 @@
1
+ import { DeleteDTO } from '@hed-hog/api';
2
+ import { PaginationDTO, PaginationService } from '@hed-hog/api-pagination';
3
+ import { PrismaService } from '@hed-hog/api-prisma';
4
+ import { HttpService } from '@nestjs/axios';
5
+ import {
6
+ BadRequestException,
7
+ Injectable,
8
+ Logger,
9
+ NotFoundException,
10
+ OnModuleInit,
11
+ } from '@nestjs/common';
12
+ import { firstValueFrom } from 'rxjs';
13
+ import { IntegrationDeveloperApiService } from '../integration/services/integration-developer-api.service';
14
+ import { DomainEvent } from '../integration/types';
15
+ import {
16
+ normalizeJsonObject,
17
+ renderTemplate,
18
+ summarizePayload,
19
+ } from './webhook-utils';
20
+
21
+ @Injectable()
22
+ export class EventWebhookService implements OnModuleInit {
23
+ private readonly logger = new Logger(EventWebhookService.name);
24
+ private readonly registeredEvents = new Set<string>();
25
+
26
+ constructor(
27
+ private readonly prisma: PrismaService,
28
+ private readonly pagination: PaginationService,
29
+ private readonly http: HttpService,
30
+ private readonly integrationApi: IntegrationDeveloperApiService,
31
+ ) {}
32
+
33
+ private get webhooks() {
34
+ return (this.prisma as any).event_webhook;
35
+ }
36
+
37
+ private get webhookEvents() {
38
+ return (this.prisma as any).event_webhook_event;
39
+ }
40
+
41
+ private get catalog() {
42
+ return (this.prisma as any).integration_event_catalog;
43
+ }
44
+
45
+ private get logs() {
46
+ return (this.prisma as any).event_webhook_delivery_log;
47
+ }
48
+
49
+ async onModuleInit() {
50
+ await this.registerConfiguredEvents();
51
+ }
52
+
53
+ async list(paginationParams: PaginationDTO) {
54
+ const fields = ['slug', 'name', 'description', 'url', 'method', 'status'];
55
+ const OR = this.prisma.createInsensitiveSearch(fields, paginationParams);
56
+
57
+ return this.pagination.paginate(this.webhooks, paginationParams, {
58
+ where: OR.length > 0 ? { OR } : {},
59
+ include: {
60
+ event_webhook_event: {
61
+ include: {
62
+ integration_event_catalog: true,
63
+ },
64
+ },
65
+ },
66
+ orderBy: [{ updated_at: 'desc' }, { id: 'desc' }],
67
+ });
68
+ }
69
+
70
+ async get(id: number) {
71
+ const record = await this.webhooks.findUnique({
72
+ where: { id },
73
+ include: {
74
+ event_webhook_event: {
75
+ include: {
76
+ integration_event_catalog: true,
77
+ },
78
+ },
79
+ },
80
+ });
81
+
82
+ if (!record) {
83
+ throw new NotFoundException(`Event webhook with id ${id} not found.`);
84
+ }
85
+
86
+ return record;
87
+ }
88
+
89
+ async create(data: any) {
90
+ await this.ensureSlugAvailable(data.slug);
91
+
92
+ const record = await this.webhooks.create({
93
+ data: {
94
+ ...this.normalizeWebhook(data),
95
+ event_webhook_event: {
96
+ create: this.normalizeEventIds(data.event_ids).map((eventId) => ({
97
+ integration_event_catalog_id: eventId,
98
+ })),
99
+ },
100
+ },
101
+ include: {
102
+ event_webhook_event: {
103
+ include: { integration_event_catalog: true },
104
+ },
105
+ },
106
+ });
107
+
108
+ await this.registerEventsFromWebhook(record);
109
+ return record;
110
+ }
111
+
112
+ async update(id: number, data: any) {
113
+ const existing = await this.get(id);
114
+ if (data.slug && data.slug !== existing.slug) {
115
+ await this.ensureSlugAvailable(data.slug);
116
+ }
117
+
118
+ const record = await this.webhooks.update({
119
+ where: { id },
120
+ data: this.normalizeWebhook(data, true),
121
+ include: {
122
+ event_webhook_event: {
123
+ include: { integration_event_catalog: true },
124
+ },
125
+ },
126
+ });
127
+
128
+ if (data.event_ids !== undefined) {
129
+ await this.webhookEvents.deleteMany({
130
+ where: { event_webhook_id: id },
131
+ });
132
+
133
+ const eventIds = this.normalizeEventIds(data.event_ids);
134
+ for (const eventId of eventIds) {
135
+ await this.webhookEvents.create({
136
+ data: {
137
+ event_webhook_id: id,
138
+ integration_event_catalog_id: eventId,
139
+ },
140
+ });
141
+ }
142
+ }
143
+
144
+ const refreshed = await this.get(id);
145
+ await this.registerEventsFromWebhook(refreshed);
146
+ return refreshed;
147
+ }
148
+
149
+ async delete(data: DeleteDTO) {
150
+ if (!data.ids?.length) {
151
+ throw new BadRequestException('You must select at least one item to delete.');
152
+ }
153
+
154
+ return this.webhooks.deleteMany({
155
+ where: { id: { in: data.ids } },
156
+ });
157
+ }
158
+
159
+ async listLogs(webhookId: number, paginationParams: PaginationDTO) {
160
+ await this.get(webhookId);
161
+ return this.pagination.paginate(this.logs, paginationParams, {
162
+ where: { event_webhook_id: webhookId },
163
+ orderBy: [{ created_at: 'desc' }, { id: 'desc' }],
164
+ });
165
+ }
166
+
167
+ async handleEvent(event: DomainEvent) {
168
+ const webhooks = await this.findActiveWebhooksForEvent(event.eventName);
169
+
170
+ for (const webhook of webhooks) {
171
+ await this.deliverWebhook(webhook, event);
172
+ }
173
+ }
174
+
175
+ async registerConfiguredEvents() {
176
+ const rows = await this.catalog.findMany({
177
+ where: {
178
+ status: 'active',
179
+ event_webhook_event: {
180
+ some: {
181
+ event_webhook: {
182
+ status: 'active',
183
+ },
184
+ },
185
+ },
186
+ },
187
+ select: { slug: true },
188
+ });
189
+
190
+ for (const row of rows) {
191
+ this.registerEvent(row.slug);
192
+ }
193
+ }
194
+
195
+ private async findActiveWebhooksForEvent(eventName: string) {
196
+ return this.webhooks.findMany({
197
+ where: {
198
+ status: 'active',
199
+ event_webhook_event: {
200
+ some: {
201
+ integration_event_catalog: {
202
+ slug: eventName,
203
+ status: 'active',
204
+ },
205
+ },
206
+ },
207
+ },
208
+ include: {
209
+ event_webhook_event: {
210
+ include: {
211
+ integration_event_catalog: true,
212
+ },
213
+ },
214
+ },
215
+ orderBy: [{ priority: 'desc' }, { id: 'asc' }],
216
+ });
217
+ }
218
+
219
+ private async deliverWebhook(webhook: any, event: DomainEvent) {
220
+ const startedAt = Date.now();
221
+ let attemptCount = 0;
222
+ let lastError: any = null;
223
+ let httpStatus: number | null = null;
224
+ let responseSummary: any = null;
225
+
226
+ const context = {
227
+ ...event,
228
+ timestamp: event.timestamp?.toISOString?.() ?? event.timestamp,
229
+ outboxEventId: (event as any).outboxEventId ?? null,
230
+ };
231
+
232
+ const url = renderTemplate(webhook.url, context) as string;
233
+ const method = webhook.method || 'POST';
234
+ const headers = renderTemplate(webhook.headers || {}, context) as Record<string, string>;
235
+ const query = renderTemplate(webhook.query || {}, context) as Record<string, string>;
236
+ const payload = renderTemplate(webhook.payload ?? event.payload ?? {}, context);
237
+ const maxAttempts = Math.max(1, Number(webhook.retry_count || 0) + 1);
238
+
239
+ for (attemptCount = 1; attemptCount <= maxAttempts; attemptCount++) {
240
+ try {
241
+ const result = await firstValueFrom(
242
+ this.http.request({
243
+ url,
244
+ method,
245
+ headers,
246
+ params: query,
247
+ data: ['GET', 'DELETE'].includes(method) ? undefined : payload,
248
+ timeout: Number(webhook.timeout_ms || 10000),
249
+ }),
250
+ );
251
+
252
+ httpStatus = result.status;
253
+ responseSummary = summarizePayload(result.data);
254
+ lastError = null;
255
+ break;
256
+ } catch (error: any) {
257
+ lastError = error;
258
+ httpStatus = error?.response?.status ?? null;
259
+ responseSummary = summarizePayload(error?.response?.data);
260
+ }
261
+ }
262
+
263
+ const success = !lastError;
264
+ await this.logs.create({
265
+ data: {
266
+ event_webhook_id: webhook.id,
267
+ integration_event_catalog_id:
268
+ webhook.event_webhook_event?.[0]?.integration_event_catalog?.id ?? null,
269
+ outbox_event_id: Number((event as any).outboxEventId || 0) || null,
270
+ event_name: event.eventName,
271
+ method,
272
+ url,
273
+ status: success ? 'success' : 'failed',
274
+ http_status: httpStatus,
275
+ duration_ms: Date.now() - startedAt,
276
+ attempt_count: attemptCount,
277
+ error_message: lastError
278
+ ? lastError instanceof Error
279
+ ? lastError.message
280
+ : String(lastError)
281
+ : null,
282
+ request_summary: summarizePayload({
283
+ headers,
284
+ query,
285
+ payload,
286
+ }),
287
+ response_summary: responseSummary,
288
+ },
289
+ });
290
+
291
+ if (!success) {
292
+ throw lastError;
293
+ }
294
+ }
295
+
296
+ private async registerEventsFromWebhook(webhook: any) {
297
+ const eventNames =
298
+ webhook.event_webhook_event
299
+ ?.map((row: any) => row.integration_event_catalog?.slug)
300
+ .filter(Boolean) || [];
301
+
302
+ for (const eventName of eventNames) {
303
+ this.registerEvent(eventName);
304
+ }
305
+ }
306
+
307
+ private registerEvent(eventName: string) {
308
+ if (this.registeredEvents.has(eventName)) {
309
+ return;
310
+ }
311
+
312
+ this.integrationApi.subscribe({
313
+ eventName,
314
+ consumerName: `core.event-webhook.${eventName}`,
315
+ priority: -100,
316
+ handler: async (event) => {
317
+ await this.handleEvent(event);
318
+ },
319
+ });
320
+
321
+ this.registeredEvents.add(eventName);
322
+ this.logger.log(`Registered event webhook dispatcher for ${eventName}`);
323
+ }
324
+
325
+ private async ensureSlugAvailable(slug: string) {
326
+ const existing = await this.webhooks.findUnique({
327
+ where: { slug: String(slug || '').trim() },
328
+ select: { id: true },
329
+ });
330
+
331
+ if (existing) {
332
+ throw new BadRequestException(`Event webhook "${slug}" already exists.`);
333
+ }
334
+ }
335
+
336
+ private normalizeWebhook(data: any, partial = false) {
337
+ const normalized: Record<string, any> = {};
338
+ const assign = (key: string, value: any) => {
339
+ if (!partial || value !== undefined) {
340
+ normalized[key] = value;
341
+ }
342
+ };
343
+
344
+ assign('slug', String(data.slug ?? '').trim());
345
+ assign('name', String(data.name ?? '').trim());
346
+ assign('description', this.nullableString(data.description, partial));
347
+ assign('status', data.status === 'inactive' ? 'inactive' : 'active');
348
+ assign('priority', Number(data.priority ?? 0));
349
+ assign('url', String(data.url ?? '').trim());
350
+ assign('method', String(data.method || 'POST').toUpperCase());
351
+ assign('headers', normalizeJsonObject(data.headers));
352
+ assign('query', normalizeJsonObject(data.query));
353
+ assign('payload', normalizeJsonObject(data.payload));
354
+ assign('timeout_ms', Number(data.timeout_ms || 10000));
355
+ assign('retry_count', Number(data.retry_count || 0));
356
+
357
+ return normalized;
358
+ }
359
+
360
+ private normalizeEventIds(value: any) {
361
+ if (!value) {
362
+ return [];
363
+ }
364
+
365
+ const values = Array.isArray(value) ? value : String(value).split(',');
366
+ return values
367
+ .map((item) => Number(item))
368
+ .filter((item) => Number.isFinite(item) && item > 0);
369
+ }
370
+
371
+ private nullableString(value: any, partial = false) {
372
+ if (value === undefined) {
373
+ return partial ? undefined : null;
374
+ }
375
+
376
+ if (value === null) {
377
+ return null;
378
+ }
379
+
380
+ const normalized = String(value).trim();
381
+ return normalized || null;
382
+ }
383
+ }
384
+
@@ -0,0 +1,50 @@
1
+ import { DeleteDTO, Role } from '@hed-hog/api';
2
+ import { Pagination } from '@hed-hog/api-pagination';
3
+ import {
4
+ Body,
5
+ Controller,
6
+ Delete,
7
+ Get,
8
+ Param,
9
+ ParseIntPipe,
10
+ Patch,
11
+ Post,
12
+ } from '@nestjs/common';
13
+ import { IntegrationEventCatalogService } from './integration-event-catalog.service';
14
+
15
+ @Role()
16
+ @Controller('integration-event-catalog')
17
+ export class IntegrationEventCatalogController {
18
+ constructor(private readonly service: IntegrationEventCatalogService) {}
19
+
20
+ @Get()
21
+ list(@Pagination() paginationParams) {
22
+ return this.service.list(paginationParams);
23
+ }
24
+
25
+ @Get('options')
26
+ options() {
27
+ return this.service.options();
28
+ }
29
+
30
+ @Get(':id')
31
+ get(@Param('id', ParseIntPipe) id: number) {
32
+ return this.service.get(id);
33
+ }
34
+
35
+ @Post()
36
+ create(@Body() data: any) {
37
+ return this.service.create(data);
38
+ }
39
+
40
+ @Patch(':id')
41
+ update(@Param('id', ParseIntPipe) id: number, @Body() data: any) {
42
+ return this.service.update(id, data);
43
+ }
44
+
45
+ @Delete()
46
+ delete(@Body() data: DeleteDTO) {
47
+ return this.service.delete(data);
48
+ }
49
+ }
50
+
@@ -0,0 +1,117 @@
1
+ import { DeleteDTO } from '@hed-hog/api';
2
+ import { PaginationDTO, PaginationService } from '@hed-hog/api-pagination';
3
+ import { PrismaService } from '@hed-hog/api-prisma';
4
+ import {
5
+ BadRequestException,
6
+ Injectable,
7
+ NotFoundException,
8
+ } from '@nestjs/common';
9
+
10
+ @Injectable()
11
+ export class IntegrationEventCatalogService {
12
+ constructor(
13
+ private readonly prisma: PrismaService,
14
+ private readonly pagination: PaginationService,
15
+ ) {}
16
+
17
+ private get delegate() {
18
+ return (this.prisma as any).integration_event_catalog;
19
+ }
20
+
21
+ async list(paginationParams: PaginationDTO) {
22
+ const fields = ['slug', 'name', 'module', 'description', 'status'];
23
+ const OR = this.prisma.createInsensitiveSearch(fields, paginationParams);
24
+
25
+ return this.pagination.paginate(this.delegate, paginationParams, {
26
+ where: OR.length > 0 ? { OR } : {},
27
+ orderBy: [{ module: 'asc' }, { slug: 'asc' }],
28
+ });
29
+ }
30
+
31
+ async options() {
32
+ return this.delegate.findMany({
33
+ where: { status: 'active' },
34
+ orderBy: [{ module: 'asc' }, { slug: 'asc' }],
35
+ select: {
36
+ id: true,
37
+ slug: true,
38
+ name: true,
39
+ module: true,
40
+ description: true,
41
+ },
42
+ });
43
+ }
44
+
45
+ async get(id: number) {
46
+ const record = await this.delegate.findUnique({ where: { id } });
47
+ if (!record) {
48
+ throw new NotFoundException(`Event catalog item with id ${id} not found.`);
49
+ }
50
+ return record;
51
+ }
52
+
53
+ async create(data: any) {
54
+ await this.ensureSlugAvailable(data.slug);
55
+ return this.delegate.create({
56
+ data: this.normalize(data),
57
+ });
58
+ }
59
+
60
+ async update(id: number, data: any) {
61
+ const existing = await this.get(id);
62
+ if (data.slug && data.slug !== existing.slug) {
63
+ await this.ensureSlugAvailable(data.slug);
64
+ }
65
+
66
+ return this.delegate.update({
67
+ where: { id },
68
+ data: this.normalize(data, true),
69
+ });
70
+ }
71
+
72
+ async delete(data: DeleteDTO) {
73
+ if (!data.ids?.length) {
74
+ throw new BadRequestException('You must select at least one item to delete.');
75
+ }
76
+
77
+ return this.delegate.deleteMany({
78
+ where: { id: { in: data.ids } },
79
+ });
80
+ }
81
+
82
+ private async ensureSlugAvailable(slug: string) {
83
+ const existing = await this.delegate.findUnique({
84
+ where: { slug: String(slug || '').trim() },
85
+ select: { id: true },
86
+ });
87
+
88
+ if (existing) {
89
+ throw new BadRequestException(`Event "${slug}" already exists.`);
90
+ }
91
+ }
92
+
93
+ private normalize(data: any, partial = false) {
94
+ const normalized: Record<string, any> = {};
95
+ const assign = (key: string, value: any) => {
96
+ if (!partial || value !== undefined) {
97
+ normalized[key] = value;
98
+ }
99
+ };
100
+
101
+ assign('slug', String(data.slug ?? '').trim());
102
+ assign('name', String(data.name ?? '').trim());
103
+ assign('module', String(data.module ?? '').trim());
104
+ assign(
105
+ 'description',
106
+ data.description === undefined || data.description === null
107
+ ? partial
108
+ ? undefined
109
+ : null
110
+ : String(data.description).trim() || null,
111
+ );
112
+ assign('status', data.status === 'inactive' ? 'inactive' : 'active');
113
+
114
+ return normalized;
115
+ }
116
+ }
117
+
@@ -0,0 +1,103 @@
1
+ import { DeleteDTO, Public, Role } from '@hed-hog/api';
2
+ import { Pagination } from '@hed-hog/api-pagination';
3
+ import {
4
+ Body,
5
+ Controller,
6
+ Delete,
7
+ Get,
8
+ Headers,
9
+ Param,
10
+ ParseIntPipe,
11
+ Patch,
12
+ Post,
13
+ Req,
14
+ } from '@nestjs/common';
15
+ import { Request } from 'express';
16
+ import { WebhookIntegrationService } from './webhook-integration.service';
17
+
18
+ @Role()
19
+ @Controller('webhook-integration')
20
+ export class WebhookIntegrationController {
21
+ constructor(private readonly service: WebhookIntegrationService) {}
22
+
23
+ @Get()
24
+ list(@Pagination() paginationParams) {
25
+ return this.service.list(paginationParams);
26
+ }
27
+
28
+ @Get(':id')
29
+ get(@Param('id', ParseIntPipe) id: number) {
30
+ return this.service.get(id);
31
+ }
32
+
33
+ @Post()
34
+ create(@Body() data: any) {
35
+ return this.service.create(data);
36
+ }
37
+
38
+ @Patch(':id')
39
+ update(@Param('id', ParseIntPipe) id: number, @Body() data: any) {
40
+ return this.service.update(id, data);
41
+ }
42
+
43
+ @Delete()
44
+ delete(@Body() data: DeleteDTO) {
45
+ return this.service.delete(data);
46
+ }
47
+
48
+ @Post(':id/regenerate-uuid')
49
+ regenerateUuid(@Param('id', ParseIntPipe) id: number) {
50
+ return this.service.regenerateUuid(id);
51
+ }
52
+
53
+ @Post(':id/regenerate-token')
54
+ regenerateToken(@Param('id', ParseIntPipe) id: number) {
55
+ return this.service.regenerateToken(id);
56
+ }
57
+
58
+ @Get(':id/action')
59
+ listActions(@Param('id', ParseIntPipe) id: number) {
60
+ return this.service.listActions(id);
61
+ }
62
+
63
+ @Post(':id/action')
64
+ createAction(@Param('id', ParseIntPipe) id: number, @Body() data: any) {
65
+ return this.service.createAction(id, data);
66
+ }
67
+
68
+ @Patch(':id/action/:actionId')
69
+ updateAction(
70
+ @Param('id', ParseIntPipe) id: number,
71
+ @Param('actionId', ParseIntPipe) actionId: number,
72
+ @Body() data: any,
73
+ ) {
74
+ return this.service.updateAction(id, actionId, data);
75
+ }
76
+
77
+ @Delete(':id/action')
78
+ deleteActions(@Param('id', ParseIntPipe) id: number, @Body() data: DeleteDTO) {
79
+ return this.service.deleteActions(id, data);
80
+ }
81
+
82
+ @Get(':id/log')
83
+ listLogs(@Param('id', ParseIntPipe) id: number, @Pagination() paginationParams) {
84
+ return this.service.listLogs(id, paginationParams);
85
+ }
86
+ }
87
+
88
+ @Public()
89
+ @Controller('webhook')
90
+ export class PublicWebhookController {
91
+ constructor(private readonly service: WebhookIntegrationService) {}
92
+
93
+ @Post(':uuid')
94
+ execute(
95
+ @Param('uuid') uuid: string,
96
+ @Body() body: any,
97
+ @Headers() headers: any,
98
+ @Req() req: Request,
99
+ ) {
100
+ return this.service.executePublic(uuid, body, headers, req);
101
+ }
102
+ }
103
+
@@ -0,0 +1,45 @@
1
+ import { MailModule as MailMainModule } from '@hed-hog/api-mail';
2
+ import { PaginationModule } from '@hed-hog/api-pagination';
3
+ import { PrismaModule } from '@hed-hog/api-prisma';
4
+ import { HttpModule } from '@nestjs/axios';
5
+ import { Module, forwardRef } from '@nestjs/common';
6
+ import { IntegrationModule } from '../integration/integration.module';
7
+ import { MailModule } from '../mail/mail.module';
8
+ import { EventWebhookController } from './event-webhook.controller';
9
+ import { EventWebhookService } from './event-webhook.service';
10
+ import { IntegrationEventCatalogController } from './integration-event-catalog.controller';
11
+ import { IntegrationEventCatalogService } from './integration-event-catalog.service';
12
+ import {
13
+ PublicWebhookController,
14
+ WebhookIntegrationController,
15
+ } from './webhook-integration.controller';
16
+ import { WebhookIntegrationService } from './webhook-integration.service';
17
+
18
+ @Module({
19
+ imports: [
20
+ HttpModule,
21
+ forwardRef(() => PrismaModule),
22
+ forwardRef(() => PaginationModule),
23
+ forwardRef(() => IntegrationModule),
24
+ forwardRef(() => MailModule),
25
+ forwardRef(() => MailMainModule),
26
+ ],
27
+ controllers: [
28
+ IntegrationEventCatalogController,
29
+ WebhookIntegrationController,
30
+ PublicWebhookController,
31
+ EventWebhookController,
32
+ ],
33
+ providers: [
34
+ IntegrationEventCatalogService,
35
+ WebhookIntegrationService,
36
+ EventWebhookService,
37
+ ],
38
+ exports: [
39
+ IntegrationEventCatalogService,
40
+ WebhookIntegrationService,
41
+ EventWebhookService,
42
+ ],
43
+ })
44
+ export class WebhookIntegrationModule {}
45
+