@open-mercato/webhooks 0.4.9-canary-8c762104f0

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 (60) hide show
  1. package/CLAUDE.md +1 -0
  2. package/build.mjs +69 -0
  3. package/dist/index.js +5 -0
  4. package/dist/index.js.map +7 -0
  5. package/dist/modules/webhooks/acl.js +14 -0
  6. package/dist/modules/webhooks/acl.js.map +7 -0
  7. package/dist/modules/webhooks/api/openapi.js +8 -0
  8. package/dist/modules/webhooks/api/openapi.js.map +7 -0
  9. package/dist/modules/webhooks/api/webhook-deliveries/route.js +118 -0
  10. package/dist/modules/webhooks/api/webhook-deliveries/route.js.map +7 -0
  11. package/dist/modules/webhooks/api/webhooks/route.js +268 -0
  12. package/dist/modules/webhooks/api/webhooks/route.js.map +7 -0
  13. package/dist/modules/webhooks/backend/webhooks/[id]/page.meta.js +17 -0
  14. package/dist/modules/webhooks/backend/webhooks/[id]/page.meta.js.map +7 -0
  15. package/dist/modules/webhooks/backend/webhooks/create/page.meta.js +17 -0
  16. package/dist/modules/webhooks/backend/webhooks/create/page.meta.js.map +7 -0
  17. package/dist/modules/webhooks/backend/webhooks/page.meta.js +24 -0
  18. package/dist/modules/webhooks/backend/webhooks/page.meta.js.map +7 -0
  19. package/dist/modules/webhooks/data/entities.js +196 -0
  20. package/dist/modules/webhooks/data/entities.js.map +7 -0
  21. package/dist/modules/webhooks/data/validators.js +39 -0
  22. package/dist/modules/webhooks/data/validators.js.map +7 -0
  23. package/dist/modules/webhooks/events.js +18 -0
  24. package/dist/modules/webhooks/events.js.map +7 -0
  25. package/dist/modules/webhooks/index.js +14 -0
  26. package/dist/modules/webhooks/index.js.map +7 -0
  27. package/dist/modules/webhooks/setup.js +12 -0
  28. package/dist/modules/webhooks/setup.js.map +7 -0
  29. package/dist/modules/webhooks/subscribers/outbound-dispatch.js +67 -0
  30. package/dist/modules/webhooks/subscribers/outbound-dispatch.js.map +7 -0
  31. package/dist/modules/webhooks/workers/webhook-delivery.js +129 -0
  32. package/dist/modules/webhooks/workers/webhook-delivery.js.map +7 -0
  33. package/generated/entities/webhook_delivery_entity/index.ts +22 -0
  34. package/generated/entities/webhook_entity/index.ts +26 -0
  35. package/generated/entities.ids.generated.ts +12 -0
  36. package/generated/entity-fields-registry.ts +13 -0
  37. package/jest.config.cjs +20 -0
  38. package/package.json +77 -0
  39. package/src/index.ts +1 -0
  40. package/src/modules/webhooks/acl.ts +10 -0
  41. package/src/modules/webhooks/api/openapi.ts +5 -0
  42. package/src/modules/webhooks/api/webhook-deliveries/route.ts +131 -0
  43. package/src/modules/webhooks/api/webhooks/route.ts +288 -0
  44. package/src/modules/webhooks/backend/webhooks/[id]/page.meta.ts +13 -0
  45. package/src/modules/webhooks/backend/webhooks/[id]/page.tsx +262 -0
  46. package/src/modules/webhooks/backend/webhooks/create/page.meta.ts +13 -0
  47. package/src/modules/webhooks/backend/webhooks/create/page.tsx +75 -0
  48. package/src/modules/webhooks/backend/webhooks/page.meta.ts +20 -0
  49. package/src/modules/webhooks/backend/webhooks/page.tsx +206 -0
  50. package/src/modules/webhooks/data/entities.ts +157 -0
  51. package/src/modules/webhooks/data/validators.ts +40 -0
  52. package/src/modules/webhooks/events.ts +15 -0
  53. package/src/modules/webhooks/i18n/en.json +73 -0
  54. package/src/modules/webhooks/index.ts +12 -0
  55. package/src/modules/webhooks/setup.ts +10 -0
  56. package/src/modules/webhooks/subscribers/outbound-dispatch.ts +79 -0
  57. package/src/modules/webhooks/workers/webhook-delivery.ts +158 -0
  58. package/tsconfig.build.json +13 -0
  59. package/tsconfig.json +9 -0
  60. package/watch.mjs +6 -0
@@ -0,0 +1,24 @@
1
+ import React from "react";
2
+ const webhookIcon = React.createElement(
3
+ "svg",
4
+ { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" },
5
+ React.createElement("path", { d: "M18 16.98h1a2 2 0 0 0 2-2v-1a2 2 0 0 0-4 0v4a2 2 0 0 1-4 0v-1a2 2 0 0 1 2-2h1" }),
6
+ React.createElement("path", { d: "M2 12a10 10 0 0 1 18-6" }),
7
+ React.createElement("path", { d: "M12 2a10 10 0 0 1 6 18" })
8
+ );
9
+ const metadata = {
10
+ requireAuth: true,
11
+ requireFeatures: ["webhooks.view"],
12
+ pageTitle: "Webhooks",
13
+ pageTitleKey: "webhooks.nav.title",
14
+ pageGroup: "Integrations",
15
+ pageGroupKey: "webhooks.nav.group",
16
+ pageOrder: 1,
17
+ icon: webhookIcon,
18
+ pageContext: "settings",
19
+ breadcrumb: [{ label: "Webhooks", labelKey: "webhooks.nav.title" }]
20
+ };
21
+ export {
22
+ metadata
23
+ };
24
+ //# sourceMappingURL=page.meta.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/webhooks/backend/webhooks/page.meta.ts"],
4
+ "sourcesContent": ["import React from 'react'\n\nconst webhookIcon = React.createElement('svg', { width: 16, height: 16, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round' },\n React.createElement('path', { d: 'M18 16.98h1a2 2 0 0 0 2-2v-1a2 2 0 0 0-4 0v4a2 2 0 0 1-4 0v-1a2 2 0 0 1 2-2h1' }),\n React.createElement('path', { d: 'M2 12a10 10 0 0 1 18-6' }),\n React.createElement('path', { d: 'M12 2a10 10 0 0 1 6 18' }),\n)\n\nexport const metadata = {\n requireAuth: true,\n requireFeatures: ['webhooks.view'],\n pageTitle: 'Webhooks',\n pageTitleKey: 'webhooks.nav.title',\n pageGroup: 'Integrations',\n pageGroupKey: 'webhooks.nav.group',\n pageOrder: 1,\n icon: webhookIcon,\n pageContext: 'settings' as const,\n breadcrumb: [{ label: 'Webhooks', labelKey: 'webhooks.nav.title' }],\n}\n"],
5
+ "mappings": "AAAA,OAAO,WAAW;AAElB,MAAM,cAAc,MAAM;AAAA,EAAc;AAAA,EAAO,EAAE,OAAO,IAAI,QAAQ,IAAI,SAAS,aAAa,MAAM,QAAQ,QAAQ,gBAAgB,aAAa,GAAG,eAAe,SAAS,gBAAgB,QAAQ;AAAA,EAClM,MAAM,cAAc,QAAQ,EAAE,GAAG,gFAAgF,CAAC;AAAA,EAClH,MAAM,cAAc,QAAQ,EAAE,GAAG,yBAAyB,CAAC;AAAA,EAC3D,MAAM,cAAc,QAAQ,EAAE,GAAG,yBAAyB,CAAC;AAC7D;AAEO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,eAAe;AAAA,EACjC,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,MAAM;AAAA,EACN,aAAa;AAAA,EACb,YAAY,CAAC,EAAE,OAAO,YAAY,UAAU,qBAAqB,CAAC;AACpE;",
6
+ "names": []
7
+ }
@@ -0,0 +1,196 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __decorateClass = (decorators, target, key, kind) => {
4
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
5
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
+ if (decorator = decorators[i])
7
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
+ if (kind && result) __defProp(target, key, result);
9
+ return result;
10
+ };
11
+ import { Entity, PrimaryKey, Property, Index } from "@mikro-orm/core";
12
+ let WebhookEntity = class {
13
+ constructor() {
14
+ this.httpMethod = "POST";
15
+ this.isActive = true;
16
+ this.deliveryStrategy = "http";
17
+ this.maxRetries = 10;
18
+ this.timeoutMs = 15e3;
19
+ this.rateLimitPerMinute = 0;
20
+ this.consecutiveFailures = 0;
21
+ this.autoDisableThreshold = 100;
22
+ this.createdAt = /* @__PURE__ */ new Date();
23
+ this.updatedAt = /* @__PURE__ */ new Date();
24
+ }
25
+ };
26
+ __decorateClass([
27
+ PrimaryKey({ type: "uuid", defaultRaw: "gen_random_uuid()" })
28
+ ], WebhookEntity.prototype, "id", 2);
29
+ __decorateClass([
30
+ Property({ type: "text" })
31
+ ], WebhookEntity.prototype, "name", 2);
32
+ __decorateClass([
33
+ Property({ name: "description", type: "text", nullable: true })
34
+ ], WebhookEntity.prototype, "description", 2);
35
+ __decorateClass([
36
+ Property({ name: "url", type: "text" })
37
+ ], WebhookEntity.prototype, "url", 2);
38
+ __decorateClass([
39
+ Property({ name: "secret", type: "text" })
40
+ ], WebhookEntity.prototype, "secret", 2);
41
+ __decorateClass([
42
+ Property({ name: "previous_secret", type: "text", nullable: true })
43
+ ], WebhookEntity.prototype, "previousSecret", 2);
44
+ __decorateClass([
45
+ Property({ name: "previous_secret_set_at", type: Date, nullable: true })
46
+ ], WebhookEntity.prototype, "previousSecretSetAt", 2);
47
+ __decorateClass([
48
+ Property({ name: "subscribed_events", type: "json" })
49
+ ], WebhookEntity.prototype, "subscribedEvents", 2);
50
+ __decorateClass([
51
+ Property({ name: "http_method", type: "text", default: "'POST'" })
52
+ ], WebhookEntity.prototype, "httpMethod", 2);
53
+ __decorateClass([
54
+ Property({ name: "custom_headers", type: "json", nullable: true })
55
+ ], WebhookEntity.prototype, "customHeaders", 2);
56
+ __decorateClass([
57
+ Property({ name: "is_active", type: "boolean", default: true })
58
+ ], WebhookEntity.prototype, "isActive", 2);
59
+ __decorateClass([
60
+ Property({ name: "delivery_strategy", type: "text", default: "'http'" })
61
+ ], WebhookEntity.prototype, "deliveryStrategy", 2);
62
+ __decorateClass([
63
+ Property({ name: "strategy_config", type: "json", nullable: true })
64
+ ], WebhookEntity.prototype, "strategyConfig", 2);
65
+ __decorateClass([
66
+ Property({ name: "max_retries", type: "int", default: 10 })
67
+ ], WebhookEntity.prototype, "maxRetries", 2);
68
+ __decorateClass([
69
+ Property({ name: "timeout_ms", type: "int", default: 15e3 })
70
+ ], WebhookEntity.prototype, "timeoutMs", 2);
71
+ __decorateClass([
72
+ Property({ name: "rate_limit_per_minute", type: "int", default: 0 })
73
+ ], WebhookEntity.prototype, "rateLimitPerMinute", 2);
74
+ __decorateClass([
75
+ Property({ name: "consecutive_failures", type: "int", default: 0 })
76
+ ], WebhookEntity.prototype, "consecutiveFailures", 2);
77
+ __decorateClass([
78
+ Property({ name: "auto_disable_threshold", type: "int", default: 100 })
79
+ ], WebhookEntity.prototype, "autoDisableThreshold", 2);
80
+ __decorateClass([
81
+ Property({ name: "last_success_at", type: Date, nullable: true })
82
+ ], WebhookEntity.prototype, "lastSuccessAt", 2);
83
+ __decorateClass([
84
+ Property({ name: "last_failure_at", type: Date, nullable: true })
85
+ ], WebhookEntity.prototype, "lastFailureAt", 2);
86
+ __decorateClass([
87
+ Property({ name: "integration_id", type: "text", nullable: true })
88
+ ], WebhookEntity.prototype, "integrationId", 2);
89
+ __decorateClass([
90
+ Property({ name: "organization_id", type: "uuid" })
91
+ ], WebhookEntity.prototype, "organizationId", 2);
92
+ __decorateClass([
93
+ Property({ name: "tenant_id", type: "uuid" })
94
+ ], WebhookEntity.prototype, "tenantId", 2);
95
+ __decorateClass([
96
+ Property({ name: "created_at", type: Date, onCreate: () => /* @__PURE__ */ new Date() })
97
+ ], WebhookEntity.prototype, "createdAt", 2);
98
+ __decorateClass([
99
+ Property({ name: "updated_at", type: Date, onUpdate: () => /* @__PURE__ */ new Date() })
100
+ ], WebhookEntity.prototype, "updatedAt", 2);
101
+ __decorateClass([
102
+ Property({ name: "deleted_at", type: Date, nullable: true })
103
+ ], WebhookEntity.prototype, "deletedAt", 2);
104
+ WebhookEntity = __decorateClass([
105
+ Entity({ tableName: "webhooks" }),
106
+ Index({ properties: ["organizationId", "tenantId", "isActive"] }),
107
+ Index({ properties: ["organizationId", "tenantId", "deletedAt"] })
108
+ ], WebhookEntity);
109
+ let WebhookDeliveryEntity = class {
110
+ constructor() {
111
+ this.status = "pending";
112
+ this.attemptNumber = 0;
113
+ this.maxAttempts = 10;
114
+ this.enqueuedAt = /* @__PURE__ */ new Date();
115
+ this.createdAt = /* @__PURE__ */ new Date();
116
+ this.updatedAt = /* @__PURE__ */ new Date();
117
+ }
118
+ };
119
+ __decorateClass([
120
+ PrimaryKey({ type: "uuid", defaultRaw: "gen_random_uuid()" })
121
+ ], WebhookDeliveryEntity.prototype, "id", 2);
122
+ __decorateClass([
123
+ Property({ name: "webhook_id", type: "uuid" })
124
+ ], WebhookDeliveryEntity.prototype, "webhookId", 2);
125
+ __decorateClass([
126
+ Property({ name: "event_type", type: "text" })
127
+ ], WebhookDeliveryEntity.prototype, "eventType", 2);
128
+ __decorateClass([
129
+ Property({ name: "message_id", type: "text" })
130
+ ], WebhookDeliveryEntity.prototype, "messageId", 2);
131
+ __decorateClass([
132
+ Property({ name: "payload", type: "json" })
133
+ ], WebhookDeliveryEntity.prototype, "payload", 2);
134
+ __decorateClass([
135
+ Property({ name: "status", type: "text", default: "'pending'" })
136
+ ], WebhookDeliveryEntity.prototype, "status", 2);
137
+ __decorateClass([
138
+ Property({ name: "response_status", type: "int", nullable: true })
139
+ ], WebhookDeliveryEntity.prototype, "responseStatus", 2);
140
+ __decorateClass([
141
+ Property({ name: "response_body", type: "text", nullable: true })
142
+ ], WebhookDeliveryEntity.prototype, "responseBody", 2);
143
+ __decorateClass([
144
+ Property({ name: "response_headers", type: "json", nullable: true })
145
+ ], WebhookDeliveryEntity.prototype, "responseHeaders", 2);
146
+ __decorateClass([
147
+ Property({ name: "error_message", type: "text", nullable: true })
148
+ ], WebhookDeliveryEntity.prototype, "errorMessage", 2);
149
+ __decorateClass([
150
+ Property({ name: "attempt_number", type: "int", default: 0 })
151
+ ], WebhookDeliveryEntity.prototype, "attemptNumber", 2);
152
+ __decorateClass([
153
+ Property({ name: "max_attempts", type: "int", default: 10 })
154
+ ], WebhookDeliveryEntity.prototype, "maxAttempts", 2);
155
+ __decorateClass([
156
+ Property({ name: "next_retry_at", type: Date, nullable: true })
157
+ ], WebhookDeliveryEntity.prototype, "nextRetryAt", 2);
158
+ __decorateClass([
159
+ Property({ name: "duration_ms", type: "int", nullable: true })
160
+ ], WebhookDeliveryEntity.prototype, "durationMs", 2);
161
+ __decorateClass([
162
+ Property({ name: "target_url", type: "text" })
163
+ ], WebhookDeliveryEntity.prototype, "targetUrl", 2);
164
+ __decorateClass([
165
+ Property({ name: "enqueued_at", type: Date })
166
+ ], WebhookDeliveryEntity.prototype, "enqueuedAt", 2);
167
+ __decorateClass([
168
+ Property({ name: "last_attempt_at", type: Date, nullable: true })
169
+ ], WebhookDeliveryEntity.prototype, "lastAttemptAt", 2);
170
+ __decorateClass([
171
+ Property({ name: "delivered_at", type: Date, nullable: true })
172
+ ], WebhookDeliveryEntity.prototype, "deliveredAt", 2);
173
+ __decorateClass([
174
+ Property({ name: "organization_id", type: "uuid" })
175
+ ], WebhookDeliveryEntity.prototype, "organizationId", 2);
176
+ __decorateClass([
177
+ Property({ name: "tenant_id", type: "uuid" })
178
+ ], WebhookDeliveryEntity.prototype, "tenantId", 2);
179
+ __decorateClass([
180
+ Property({ name: "created_at", type: Date, onCreate: () => /* @__PURE__ */ new Date() })
181
+ ], WebhookDeliveryEntity.prototype, "createdAt", 2);
182
+ __decorateClass([
183
+ Property({ name: "updated_at", type: Date, onUpdate: () => /* @__PURE__ */ new Date() })
184
+ ], WebhookDeliveryEntity.prototype, "updatedAt", 2);
185
+ WebhookDeliveryEntity = __decorateClass([
186
+ Entity({ tableName: "webhook_deliveries" }),
187
+ Index({ properties: ["webhookId", "status"] }),
188
+ Index({ properties: ["organizationId", "tenantId", "createdAt"] }),
189
+ Index({ properties: ["webhookId", "createdAt"] }),
190
+ Index({ properties: ["eventType", "organizationId"] })
191
+ ], WebhookDeliveryEntity);
192
+ export {
193
+ WebhookDeliveryEntity,
194
+ WebhookEntity
195
+ };
196
+ //# sourceMappingURL=entities.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/webhooks/data/entities.ts"],
4
+ "sourcesContent": ["import { Entity, PrimaryKey, Property, Index } from '@mikro-orm/core'\n\n@Entity({ tableName: 'webhooks' })\n@Index({ properties: ['organizationId', 'tenantId', 'isActive'] })\n@Index({ properties: ['organizationId', 'tenantId', 'deletedAt'] })\nexport class WebhookEntity {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ type: 'text' })\n name!: string\n\n @Property({ name: 'description', type: 'text', nullable: true })\n description?: string | null\n\n @Property({ name: 'url', type: 'text' })\n url!: string\n\n @Property({ name: 'secret', type: 'text' })\n secret!: string\n\n @Property({ name: 'previous_secret', type: 'text', nullable: true })\n previousSecret?: string | null\n\n @Property({ name: 'previous_secret_set_at', type: Date, nullable: true })\n previousSecretSetAt?: Date | null\n\n @Property({ name: 'subscribed_events', type: 'json' })\n subscribedEvents!: string[]\n\n @Property({ name: 'http_method', type: 'text', default: \"'POST'\" })\n httpMethod: string = 'POST'\n\n @Property({ name: 'custom_headers', type: 'json', nullable: true })\n customHeaders?: Record<string, string> | null\n\n @Property({ name: 'is_active', type: 'boolean', default: true })\n isActive: boolean = true\n\n @Property({ name: 'delivery_strategy', type: 'text', default: \"'http'\" })\n deliveryStrategy: string = 'http'\n\n @Property({ name: 'strategy_config', type: 'json', nullable: true })\n strategyConfig?: Record<string, unknown> | null\n\n @Property({ name: 'max_retries', type: 'int', default: 10 })\n maxRetries: number = 10\n\n @Property({ name: 'timeout_ms', type: 'int', default: 15000 })\n timeoutMs: number = 15000\n\n @Property({ name: 'rate_limit_per_minute', type: 'int', default: 0 })\n rateLimitPerMinute: number = 0\n\n @Property({ name: 'consecutive_failures', type: 'int', default: 0 })\n consecutiveFailures: number = 0\n\n @Property({ name: 'auto_disable_threshold', type: 'int', default: 100 })\n autoDisableThreshold: number = 100\n\n @Property({ name: 'last_success_at', type: Date, nullable: true })\n lastSuccessAt?: Date | null\n\n @Property({ name: 'last_failure_at', type: Date, nullable: true })\n lastFailureAt?: Date | null\n\n @Property({ name: 'integration_id', type: 'text', nullable: true })\n integrationId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'webhook_deliveries' })\n@Index({ properties: ['webhookId', 'status'] })\n@Index({ properties: ['organizationId', 'tenantId', 'createdAt'] })\n@Index({ properties: ['webhookId', 'createdAt'] })\n@Index({ properties: ['eventType', 'organizationId'] })\nexport class WebhookDeliveryEntity {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'webhook_id', type: 'uuid' })\n webhookId!: string\n\n @Property({ name: 'event_type', type: 'text' })\n eventType!: string\n\n @Property({ name: 'message_id', type: 'text' })\n messageId!: string\n\n @Property({ name: 'payload', type: 'json' })\n payload!: Record<string, unknown>\n\n @Property({ name: 'status', type: 'text', default: \"'pending'\" })\n status: string = 'pending'\n\n @Property({ name: 'response_status', type: 'int', nullable: true })\n responseStatus?: number | null\n\n @Property({ name: 'response_body', type: 'text', nullable: true })\n responseBody?: string | null\n\n @Property({ name: 'response_headers', type: 'json', nullable: true })\n responseHeaders?: Record<string, string> | null\n\n @Property({ name: 'error_message', type: 'text', nullable: true })\n errorMessage?: string | null\n\n @Property({ name: 'attempt_number', type: 'int', default: 0 })\n attemptNumber: number = 0\n\n @Property({ name: 'max_attempts', type: 'int', default: 10 })\n maxAttempts: number = 10\n\n @Property({ name: 'next_retry_at', type: Date, nullable: true })\n nextRetryAt?: Date | null\n\n @Property({ name: 'duration_ms', type: 'int', nullable: true })\n durationMs?: number | null\n\n @Property({ name: 'target_url', type: 'text' })\n targetUrl!: string\n\n @Property({ name: 'enqueued_at', type: Date })\n enqueuedAt: Date = new Date()\n\n @Property({ name: 'last_attempt_at', type: Date, nullable: true })\n lastAttemptAt?: Date | null\n\n @Property({ name: 'delivered_at', type: Date, nullable: true })\n deliveredAt?: Date | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,39 @@
1
+ import { z } from "zod";
2
+ const webhookCreateSchema = z.object({
3
+ name: z.string().min(1).max(255),
4
+ description: z.string().max(1e3).optional().nullable(),
5
+ url: z.string().url(),
6
+ subscribedEvents: z.array(z.string().min(1)).min(1),
7
+ httpMethod: z.enum(["POST", "PUT", "PATCH"]).default("POST"),
8
+ customHeaders: z.record(z.string(), z.string()).optional().nullable(),
9
+ deliveryStrategy: z.literal("http").default("http"),
10
+ strategyConfig: z.record(z.string(), z.unknown()).optional().nullable(),
11
+ maxRetries: z.number().int().min(0).max(30).default(10),
12
+ timeoutMs: z.number().int().min(1e3).max(6e4).default(15e3),
13
+ rateLimitPerMinute: z.number().int().min(0).max(1e4).default(0),
14
+ autoDisableThreshold: z.number().int().min(0).max(1e3).default(100),
15
+ integrationId: z.string().optional().nullable()
16
+ });
17
+ const webhookUpdateSchema = webhookCreateSchema.partial().extend({
18
+ isActive: z.boolean().optional()
19
+ });
20
+ const webhookListQuerySchema = z.object({
21
+ page: z.string().optional(),
22
+ pageSize: z.string().optional(),
23
+ search: z.string().optional(),
24
+ isActive: z.string().optional()
25
+ });
26
+ const webhookDeliveryQuerySchema = z.object({
27
+ page: z.coerce.number().min(1).default(1),
28
+ pageSize: z.coerce.number().min(1).max(100).default(50),
29
+ webhookId: z.string().uuid().optional(),
30
+ eventType: z.string().optional(),
31
+ status: z.enum(["pending", "sending", "delivered", "failed", "expired"]).optional()
32
+ });
33
+ export {
34
+ webhookCreateSchema,
35
+ webhookDeliveryQuerySchema,
36
+ webhookListQuerySchema,
37
+ webhookUpdateSchema
38
+ };
39
+ //# sourceMappingURL=validators.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/webhooks/data/validators.ts"],
4
+ "sourcesContent": ["import { z } from 'zod'\n\nexport const webhookCreateSchema = z.object({\n name: z.string().min(1).max(255),\n description: z.string().max(1000).optional().nullable(),\n url: z.string().url(),\n subscribedEvents: z.array(z.string().min(1)).min(1),\n httpMethod: z.enum(['POST', 'PUT', 'PATCH'] as const).default('POST'),\n customHeaders: z.record(z.string(), z.string()).optional().nullable(),\n deliveryStrategy: z.literal('http').default('http'),\n strategyConfig: z.record(z.string(), z.unknown()).optional().nullable(),\n maxRetries: z.number().int().min(0).max(30).default(10),\n timeoutMs: z.number().int().min(1000).max(60000).default(15000),\n rateLimitPerMinute: z.number().int().min(0).max(10000).default(0),\n autoDisableThreshold: z.number().int().min(0).max(1000).default(100),\n integrationId: z.string().optional().nullable(),\n})\n\nexport type WebhookCreateInput = z.infer<typeof webhookCreateSchema>\n\nexport const webhookUpdateSchema = webhookCreateSchema.partial().extend({\n isActive: z.boolean().optional(),\n})\n\nexport type WebhookUpdateInput = z.infer<typeof webhookUpdateSchema>\n\nexport const webhookListQuerySchema = z.object({\n page: z.string().optional(),\n pageSize: z.string().optional(),\n search: z.string().optional(),\n isActive: z.string().optional(),\n})\n\nexport const webhookDeliveryQuerySchema = z.object({\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n webhookId: z.string().uuid().optional(),\n eventType: z.string().optional(),\n status: z.enum(['pending', 'sending', 'delivered', 'failed', 'expired'] as const).optional(),\n})\n"],
5
+ "mappings": "AAAA,SAAS,SAAS;AAEX,MAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA,EAC/B,aAAa,EAAE,OAAO,EAAE,IAAI,GAAI,EAAE,SAAS,EAAE,SAAS;AAAA,EACtD,KAAK,EAAE,OAAO,EAAE,IAAI;AAAA,EACpB,kBAAkB,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC;AAAA,EAClD,YAAY,EAAE,KAAK,CAAC,QAAQ,OAAO,OAAO,CAAU,EAAE,QAAQ,MAAM;AAAA,EACpE,eAAe,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA,EACpE,kBAAkB,EAAE,QAAQ,MAAM,EAAE,QAAQ,MAAM;AAAA,EAClD,gBAAgB,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA,EACtE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE;AAAA,EACtD,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAI,EAAE,IAAI,GAAK,EAAE,QAAQ,IAAK;AAAA,EAC9D,oBAAoB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAK,EAAE,QAAQ,CAAC;AAAA,EAChE,sBAAsB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAI,EAAE,QAAQ,GAAG;AAAA,EACnE,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAChD,CAAC;AAIM,MAAM,sBAAsB,oBAAoB,QAAQ,EAAE,OAAO;AAAA,EACtE,UAAU,EAAE,QAAQ,EAAE,SAAS;AACjC,CAAC;AAIM,MAAM,yBAAyB,EAAE,OAAO;AAAA,EAC7C,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,UAAU,EAAE,OAAO,EAAE,SAAS;AAChC,CAAC;AAEM,MAAM,6BAA6B,EAAE,OAAO;AAAA,EACjD,MAAM,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;AAAA,EACxC,UAAU,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE;AAAA,EACtD,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AAAA,EACtC,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,QAAQ,EAAE,KAAK,CAAC,WAAW,WAAW,aAAa,UAAU,SAAS,CAAU,EAAE,SAAS;AAC7F,CAAC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,18 @@
1
+ import { createModuleEvents } from "@open-mercato/shared/modules/events";
2
+ const events = [
3
+ { id: "webhooks.webhook.created", label: "Webhook Created", entity: "webhook", category: "crud" },
4
+ { id: "webhooks.webhook.updated", label: "Webhook Updated", entity: "webhook", category: "crud" },
5
+ { id: "webhooks.webhook.deleted", label: "Webhook Deleted", entity: "webhook", category: "crud" },
6
+ { id: "webhooks.delivery.succeeded", label: "Webhook Delivery Succeeded", entity: "delivery", category: "lifecycle" },
7
+ { id: "webhooks.delivery.failed", label: "Webhook Delivery Failed", entity: "delivery", category: "lifecycle" },
8
+ { id: "webhooks.webhook.disabled", label: "Webhook Auto-Disabled", entity: "webhook", category: "lifecycle" }
9
+ ];
10
+ const eventsConfig = createModuleEvents({ moduleId: "webhooks", events });
11
+ const emitWebhooksEvent = eventsConfig.emit;
12
+ var events_default = eventsConfig;
13
+ export {
14
+ events_default as default,
15
+ emitWebhooksEvent,
16
+ eventsConfig
17
+ };
18
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/modules/webhooks/events.ts"],
4
+ "sourcesContent": ["import { createModuleEvents } from '@open-mercato/shared/modules/events'\n\nconst events = [\n { id: 'webhooks.webhook.created', label: 'Webhook Created', entity: 'webhook', category: 'crud' as const },\n { id: 'webhooks.webhook.updated', label: 'Webhook Updated', entity: 'webhook', category: 'crud' as const },\n { id: 'webhooks.webhook.deleted', label: 'Webhook Deleted', entity: 'webhook', category: 'crud' as const },\n { id: 'webhooks.delivery.succeeded', label: 'Webhook Delivery Succeeded', entity: 'delivery', category: 'lifecycle' as const },\n { id: 'webhooks.delivery.failed', label: 'Webhook Delivery Failed', entity: 'delivery', category: 'lifecycle' as const },\n { id: 'webhooks.webhook.disabled', label: 'Webhook Auto-Disabled', entity: 'webhook', category: 'lifecycle' as const },\n] as const\n\nexport const eventsConfig = createModuleEvents({ moduleId: 'webhooks', events })\nexport const emitWebhooksEvent = eventsConfig.emit\nexport type WebhooksEventId = typeof events[number]['id']\nexport default eventsConfig\n"],
5
+ "mappings": "AAAA,SAAS,0BAA0B;AAEnC,MAAM,SAAS;AAAA,EACb,EAAE,IAAI,4BAA4B,OAAO,mBAAmB,QAAQ,WAAW,UAAU,OAAgB;AAAA,EACzG,EAAE,IAAI,4BAA4B,OAAO,mBAAmB,QAAQ,WAAW,UAAU,OAAgB;AAAA,EACzG,EAAE,IAAI,4BAA4B,OAAO,mBAAmB,QAAQ,WAAW,UAAU,OAAgB;AAAA,EACzG,EAAE,IAAI,+BAA+B,OAAO,8BAA8B,QAAQ,YAAY,UAAU,YAAqB;AAAA,EAC7H,EAAE,IAAI,4BAA4B,OAAO,2BAA2B,QAAQ,YAAY,UAAU,YAAqB;AAAA,EACvH,EAAE,IAAI,6BAA6B,OAAO,yBAAyB,QAAQ,WAAW,UAAU,YAAqB;AACvH;AAEO,MAAM,eAAe,mBAAmB,EAAE,UAAU,YAAY,OAAO,CAAC;AACxE,MAAM,oBAAoB,aAAa;AAE9C,IAAO,iBAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,14 @@
1
+ const metadata = {
2
+ name: "webhooks",
3
+ title: "Webhooks",
4
+ version: "0.1.0",
5
+ description: "Standard Webhooks compliant outbound webhook delivery for platform events.",
6
+ author: "Open Mercato Team",
7
+ license: "Proprietary"
8
+ };
9
+ import { features } from "./acl.js";
10
+ export {
11
+ features,
12
+ metadata
13
+ };
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/modules/webhooks/index.ts"],
4
+ "sourcesContent": ["import type { ModuleInfo } from '@open-mercato/shared/modules/registry'\n\nexport const metadata: ModuleInfo = {\n name: 'webhooks',\n title: 'Webhooks',\n version: '0.1.0',\n description: 'Standard Webhooks compliant outbound webhook delivery for platform events.',\n author: 'Open Mercato Team',\n license: 'Proprietary',\n}\n\nexport { features } from './acl'\n"],
5
+ "mappings": "AAEO,MAAM,WAAuB;AAAA,EAClC,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AAAA,EACT,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,SAAS;AACX;AAEA,SAAS,gBAAgB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,12 @@
1
+ const setup = {
2
+ defaultRoleFeatures: {
3
+ admin: ["webhooks.*"],
4
+ employee: ["webhooks.view", "webhooks.deliveries.view"]
5
+ }
6
+ };
7
+ var setup_default = setup;
8
+ export {
9
+ setup_default as default,
10
+ setup
11
+ };
12
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/modules/webhooks/setup.ts"],
4
+ "sourcesContent": ["import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'\n\nexport const setup: ModuleSetupConfig = {\n defaultRoleFeatures: {\n admin: ['webhooks.*'],\n employee: ['webhooks.view', 'webhooks.deliveries.view'],\n },\n}\n\nexport default setup\n"],
5
+ "mappings": "AAEO,MAAM,QAA2B;AAAA,EACtC,qBAAqB;AAAA,IACnB,OAAO,CAAC,YAAY;AAAA,IACpB,UAAU,CAAC,iBAAiB,0BAA0B;AAAA,EACxD;AACF;AAEA,IAAO,gBAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,67 @@
1
+ import { WebhookEntity } from "../data/entities.js";
2
+ import { findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
3
+ const metadata = {
4
+ event: "*",
5
+ persistent: true,
6
+ id: "webhooks:outbound-dispatch"
7
+ };
8
+ async function handler(payload, ctx) {
9
+ const eventId = ctx.eventId ?? payload.eventId ?? payload.type;
10
+ if (!eventId) return;
11
+ const tenantId = payload.tenantId;
12
+ const organizationId = payload.organizationId;
13
+ if (!tenantId) return;
14
+ if (eventId.startsWith("webhooks.")) return;
15
+ const em = ctx.container.resolve("em").fork();
16
+ const webhooks = await findWithDecryption(
17
+ em,
18
+ WebhookEntity,
19
+ {
20
+ isActive: true,
21
+ deletedAt: null,
22
+ tenantId,
23
+ ...organizationId ? { organizationId } : {}
24
+ },
25
+ {},
26
+ { tenantId, organizationId: organizationId ?? "" }
27
+ );
28
+ if (!webhooks.length) return;
29
+ const matchingWebhooks = webhooks.filter(
30
+ (webhook) => webhook.subscribedEvents.some((pattern) => eventMatchesPattern(eventId, pattern))
31
+ );
32
+ if (!matchingWebhooks.length) return;
33
+ const queue = ctx.container.resolve("queueService");
34
+ for (const webhook of matchingWebhooks) {
35
+ try {
36
+ await queue.enqueueJob({
37
+ queue: "webhook-deliveries",
38
+ data: {
39
+ webhookId: webhook.id,
40
+ eventId,
41
+ payload,
42
+ tenantId,
43
+ organizationId: organizationId ?? webhook.organizationId
44
+ }
45
+ });
46
+ } catch {
47
+ }
48
+ }
49
+ }
50
+ function eventMatchesPattern(eventId, pattern) {
51
+ if (pattern === "*") return true;
52
+ if (pattern === eventId) return true;
53
+ if (pattern.endsWith(".*")) {
54
+ const prefix = pattern.slice(0, -2);
55
+ return eventId.startsWith(prefix + ".");
56
+ }
57
+ if (pattern.endsWith("*")) {
58
+ const prefix = pattern.slice(0, -1);
59
+ return eventId.startsWith(prefix);
60
+ }
61
+ return false;
62
+ }
63
+ export {
64
+ handler as default,
65
+ metadata
66
+ };
67
+ //# sourceMappingURL=outbound-dispatch.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/webhooks/subscribers/outbound-dispatch.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { WebhookEntity } from '../data/entities'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\n\nexport const metadata = {\n event: '*',\n persistent: true,\n id: 'webhooks:outbound-dispatch',\n}\n\nexport default async function handler(\n payload: Record<string, unknown>,\n ctx: { container: { resolve: <T = unknown>(name: string) => T }; eventId?: string },\n) {\n const eventId = ctx.eventId ?? (payload.eventId as string) ?? (payload.type as string)\n if (!eventId) return\n\n const tenantId = payload.tenantId as string | undefined\n const organizationId = payload.organizationId as string | undefined\n if (!tenantId) return\n\n if (eventId.startsWith('webhooks.')) return\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n const webhooks = await findWithDecryption(\n em,\n WebhookEntity,\n {\n isActive: true,\n deletedAt: null,\n tenantId,\n ...(organizationId ? { organizationId } : {}),\n },\n {},\n { tenantId, organizationId: organizationId ?? '' },\n )\n\n if (!webhooks.length) return\n\n const matchingWebhooks = webhooks.filter((webhook) =>\n webhook.subscribedEvents.some((pattern) => eventMatchesPattern(eventId, pattern)),\n )\n\n if (!matchingWebhooks.length) return\n\n const queue = ctx.container.resolve<{ enqueueJob: (data: unknown) => Promise<unknown> }>('queueService')\n\n for (const webhook of matchingWebhooks) {\n try {\n await queue.enqueueJob({\n queue: 'webhook-deliveries',\n data: {\n webhookId: webhook.id,\n eventId,\n payload,\n tenantId,\n organizationId: organizationId ?? webhook.organizationId,\n },\n })\n } catch {\n // Don't fail the event pipeline if queue is unavailable\n }\n }\n}\n\nfunction eventMatchesPattern(eventId: string, pattern: string): boolean {\n if (pattern === '*') return true\n if (pattern === eventId) return true\n if (pattern.endsWith('.*')) {\n const prefix = pattern.slice(0, -2)\n return eventId.startsWith(prefix + '.')\n }\n if (pattern.endsWith('*')) {\n const prefix = pattern.slice(0, -1)\n return eventId.startsWith(prefix)\n }\n return false\n}\n"],
5
+ "mappings": "AACA,SAAS,qBAAqB;AAC9B,SAAS,0BAA0B;AAE5B,MAAM,WAAW;AAAA,EACtB,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,IAAI;AACN;AAEA,eAAO,QACL,SACA,KACA;AACA,QAAM,UAAU,IAAI,WAAY,QAAQ,WAAuB,QAAQ;AACvE,MAAI,CAAC,QAAS;AAEd,QAAM,WAAW,QAAQ;AACzB,QAAM,iBAAiB,QAAQ;AAC/B,MAAI,CAAC,SAAU;AAEf,MAAI,QAAQ,WAAW,WAAW,EAAG;AAErC,QAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAE/D,QAAM,WAAW,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,MACE,UAAU;AAAA,MACV,WAAW;AAAA,MACX;AAAA,MACA,GAAI,iBAAiB,EAAE,eAAe,IAAI,CAAC;AAAA,IAC7C;AAAA,IACA,CAAC;AAAA,IACD,EAAE,UAAU,gBAAgB,kBAAkB,GAAG;AAAA,EACnD;AAEA,MAAI,CAAC,SAAS,OAAQ;AAEtB,QAAM,mBAAmB,SAAS;AAAA,IAAO,CAAC,YACxC,QAAQ,iBAAiB,KAAK,CAAC,YAAY,oBAAoB,SAAS,OAAO,CAAC;AAAA,EAClF;AAEA,MAAI,CAAC,iBAAiB,OAAQ;AAE9B,QAAM,QAAQ,IAAI,UAAU,QAA6D,cAAc;AAEvG,aAAW,WAAW,kBAAkB;AACtC,QAAI;AACF,YAAM,MAAM,WAAW;AAAA,QACrB,OAAO;AAAA,QACP,MAAM;AAAA,UACJ,WAAW,QAAQ;AAAA,UACnB;AAAA,UACA;AAAA,UACA;AAAA,UACA,gBAAgB,kBAAkB,QAAQ;AAAA,QAC5C;AAAA,MACF,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAEA,SAAS,oBAAoB,SAAiB,SAA0B;AACtE,MAAI,YAAY,IAAK,QAAO;AAC5B,MAAI,YAAY,QAAS,QAAO;AAChC,MAAI,QAAQ,SAAS,IAAI,GAAG;AAC1B,UAAM,SAAS,QAAQ,MAAM,GAAG,EAAE;AAClC,WAAO,QAAQ,WAAW,SAAS,GAAG;AAAA,EACxC;AACA,MAAI,QAAQ,SAAS,GAAG,GAAG;AACzB,UAAM,SAAS,QAAQ,MAAM,GAAG,EAAE;AAClC,WAAO,QAAQ,WAAW,MAAM;AAAA,EAClC;AACA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1,129 @@
1
+ import { WebhookEntity, WebhookDeliveryEntity } from "../data/entities.js";
2
+ import { buildWebhookHeaders, generateMessageId } from "@open-mercato/shared/lib/webhooks";
3
+ import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
4
+ const metadata = {
5
+ queue: "webhook-deliveries",
6
+ id: "webhooks:delivery-worker",
7
+ concurrency: 10
8
+ };
9
+ async function handler(job, ctx) {
10
+ const { webhookId, eventId, payload, tenantId, organizationId } = job.data;
11
+ const em = ctx.resolve("em").fork();
12
+ const webhook = await findOneWithDecryption(
13
+ em,
14
+ WebhookEntity,
15
+ { id: webhookId, isActive: true, deletedAt: null },
16
+ {},
17
+ { tenantId, organizationId }
18
+ );
19
+ if (!webhook) return;
20
+ const messageId = generateMessageId();
21
+ const timestamp = Math.floor(Date.now() / 1e3);
22
+ const body = JSON.stringify({
23
+ type: eventId,
24
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
25
+ data: payload
26
+ });
27
+ const now = /* @__PURE__ */ new Date();
28
+ const delivery = em.create(WebhookDeliveryEntity, {
29
+ webhookId: webhook.id,
30
+ eventType: eventId,
31
+ messageId,
32
+ payload: JSON.parse(body),
33
+ status: "sending",
34
+ attemptNumber: 0,
35
+ maxAttempts: webhook.maxRetries,
36
+ targetUrl: webhook.url,
37
+ organizationId: webhook.organizationId,
38
+ tenantId: webhook.tenantId,
39
+ enqueuedAt: now,
40
+ createdAt: now,
41
+ updatedAt: now
42
+ });
43
+ await em.flush();
44
+ const headers = buildWebhookHeaders(
45
+ messageId,
46
+ timestamp,
47
+ body,
48
+ webhook.secret,
49
+ webhook.previousSecret
50
+ );
51
+ const startTime = Date.now();
52
+ try {
53
+ const controller = new AbortController();
54
+ const timeoutId = setTimeout(() => controller.abort(), webhook.timeoutMs);
55
+ const response = await fetch(webhook.url, {
56
+ method: webhook.httpMethod,
57
+ headers: {
58
+ "content-type": "application/json",
59
+ ...headers,
60
+ ...webhook.customHeaders ?? {}
61
+ },
62
+ body,
63
+ signal: controller.signal
64
+ });
65
+ clearTimeout(timeoutId);
66
+ const durationMs = Date.now() - startTime;
67
+ const responseBody = await response.text().catch(() => "");
68
+ delivery.responseStatus = response.status;
69
+ delivery.responseBody = responseBody.slice(0, 4096);
70
+ delivery.durationMs = durationMs;
71
+ delivery.lastAttemptAt = /* @__PURE__ */ new Date();
72
+ delivery.attemptNumber += 1;
73
+ if (response.ok) {
74
+ delivery.status = "delivered";
75
+ delivery.deliveredAt = /* @__PURE__ */ new Date();
76
+ webhook.consecutiveFailures = 0;
77
+ webhook.lastSuccessAt = /* @__PURE__ */ new Date();
78
+ } else {
79
+ const shouldRetry = shouldRetryStatus(response.status) && delivery.attemptNumber < delivery.maxAttempts;
80
+ if (shouldRetry) {
81
+ delivery.status = "pending";
82
+ delivery.nextRetryAt = calculateNextRetry(delivery.attemptNumber);
83
+ } else {
84
+ delivery.status = "failed";
85
+ }
86
+ webhook.consecutiveFailures += 1;
87
+ webhook.lastFailureAt = /* @__PURE__ */ new Date();
88
+ if (webhook.autoDisableThreshold > 0 && webhook.consecutiveFailures >= webhook.autoDisableThreshold) {
89
+ webhook.isActive = false;
90
+ }
91
+ }
92
+ } catch (error) {
93
+ const durationMs = Date.now() - startTime;
94
+ delivery.durationMs = durationMs;
95
+ delivery.lastAttemptAt = /* @__PURE__ */ new Date();
96
+ delivery.attemptNumber += 1;
97
+ delivery.errorMessage = error instanceof Error ? error.message : "Unknown error";
98
+ const shouldRetry = delivery.attemptNumber < delivery.maxAttempts;
99
+ if (shouldRetry) {
100
+ delivery.status = "pending";
101
+ delivery.nextRetryAt = calculateNextRetry(delivery.attemptNumber);
102
+ } else {
103
+ delivery.status = "failed";
104
+ }
105
+ webhook.consecutiveFailures += 1;
106
+ webhook.lastFailureAt = /* @__PURE__ */ new Date();
107
+ if (webhook.autoDisableThreshold > 0 && webhook.consecutiveFailures >= webhook.autoDisableThreshold) {
108
+ webhook.isActive = false;
109
+ }
110
+ }
111
+ await em.flush();
112
+ }
113
+ function shouldRetryStatus(status) {
114
+ if (status >= 200 && status < 300) return false;
115
+ if (status === 408 || status === 429) return true;
116
+ if (status >= 500) return true;
117
+ return false;
118
+ }
119
+ function calculateNextRetry(attemptNumber) {
120
+ const baseDelay = 1e3;
121
+ const delayMs = baseDelay * Math.pow(2, attemptNumber - 1);
122
+ const jitter = Math.random() * 1e3;
123
+ return new Date(Date.now() + delayMs + jitter);
124
+ }
125
+ export {
126
+ handler as default,
127
+ metadata
128
+ };
129
+ //# sourceMappingURL=webhook-delivery.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/webhooks/workers/webhook-delivery.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { WebhookEntity, WebhookDeliveryEntity } from '../data/entities'\nimport { buildWebhookHeaders, generateMessageId } from '@open-mercato/shared/lib/webhooks'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\n\nexport const metadata = {\n queue: 'webhook-deliveries',\n id: 'webhooks:delivery-worker',\n concurrency: 10,\n}\n\ninterface WebhookDeliveryJob {\n webhookId: string\n eventId: string\n payload: Record<string, unknown>\n tenantId: string\n organizationId: string\n}\n\nexport default async function handler(\n job: { data: WebhookDeliveryJob },\n ctx: { resolve: <T = unknown>(name: string) => T },\n) {\n const { webhookId, eventId, payload, tenantId, organizationId } = job.data\n const em = (ctx.resolve('em') as EntityManager).fork()\n\n const webhook = await findOneWithDecryption(\n em,\n WebhookEntity,\n { id: webhookId, isActive: true, deletedAt: null },\n {},\n { tenantId, organizationId },\n )\n\n if (!webhook) return\n\n const messageId = generateMessageId()\n const timestamp = Math.floor(Date.now() / 1000)\n const body = JSON.stringify({\n type: eventId,\n timestamp: new Date().toISOString(),\n data: payload,\n })\n\n const now = new Date()\n const delivery = em.create(WebhookDeliveryEntity, {\n webhookId: webhook.id,\n eventType: eventId,\n messageId,\n payload: JSON.parse(body),\n status: 'sending',\n attemptNumber: 0,\n maxAttempts: webhook.maxRetries,\n targetUrl: webhook.url,\n organizationId: webhook.organizationId,\n tenantId: webhook.tenantId,\n enqueuedAt: now,\n createdAt: now,\n updatedAt: now,\n })\n\n await em.flush()\n\n const headers = buildWebhookHeaders(\n messageId,\n timestamp,\n body,\n webhook.secret,\n webhook.previousSecret,\n )\n\n const startTime = Date.now()\n\n try {\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), webhook.timeoutMs)\n\n const response = await fetch(webhook.url, {\n method: webhook.httpMethod,\n headers: {\n 'content-type': 'application/json',\n ...headers,\n ...(webhook.customHeaders ?? {}),\n },\n body,\n signal: controller.signal,\n })\n\n clearTimeout(timeoutId)\n\n const durationMs = Date.now() - startTime\n const responseBody = await response.text().catch(() => '')\n\n delivery.responseStatus = response.status\n delivery.responseBody = responseBody.slice(0, 4096)\n delivery.durationMs = durationMs\n delivery.lastAttemptAt = new Date()\n delivery.attemptNumber += 1\n\n if (response.ok) {\n delivery.status = 'delivered'\n delivery.deliveredAt = new Date()\n webhook.consecutiveFailures = 0\n webhook.lastSuccessAt = new Date()\n } else {\n const shouldRetry = shouldRetryStatus(response.status) && delivery.attemptNumber < delivery.maxAttempts\n if (shouldRetry) {\n delivery.status = 'pending'\n delivery.nextRetryAt = calculateNextRetry(delivery.attemptNumber)\n } else {\n delivery.status = 'failed'\n }\n webhook.consecutiveFailures += 1\n webhook.lastFailureAt = new Date()\n\n if (webhook.autoDisableThreshold > 0 && webhook.consecutiveFailures >= webhook.autoDisableThreshold) {\n webhook.isActive = false\n }\n }\n } catch (error) {\n const durationMs = Date.now() - startTime\n delivery.durationMs = durationMs\n delivery.lastAttemptAt = new Date()\n delivery.attemptNumber += 1\n delivery.errorMessage = error instanceof Error ? error.message : 'Unknown error'\n\n const shouldRetry = delivery.attemptNumber < delivery.maxAttempts\n if (shouldRetry) {\n delivery.status = 'pending'\n delivery.nextRetryAt = calculateNextRetry(delivery.attemptNumber)\n } else {\n delivery.status = 'failed'\n }\n\n webhook.consecutiveFailures += 1\n webhook.lastFailureAt = new Date()\n\n if (webhook.autoDisableThreshold > 0 && webhook.consecutiveFailures >= webhook.autoDisableThreshold) {\n webhook.isActive = false\n }\n }\n\n await em.flush()\n}\n\nfunction shouldRetryStatus(status: number): boolean {\n if (status >= 200 && status < 300) return false\n if (status === 408 || status === 429) return true\n if (status >= 500) return true\n return false\n}\n\nfunction calculateNextRetry(attemptNumber: number): Date {\n const baseDelay = 1000\n const delayMs = baseDelay * Math.pow(2, attemptNumber - 1)\n const jitter = Math.random() * 1000\n return new Date(Date.now() + delayMs + jitter)\n}\n"],
5
+ "mappings": "AACA,SAAS,eAAe,6BAA6B;AACrD,SAAS,qBAAqB,yBAAyB;AACvD,SAAS,6BAA6B;AAE/B,MAAM,WAAW;AAAA,EACtB,OAAO;AAAA,EACP,IAAI;AAAA,EACJ,aAAa;AACf;AAUA,eAAO,QACL,KACA,KACA;AACA,QAAM,EAAE,WAAW,SAAS,SAAS,UAAU,eAAe,IAAI,IAAI;AACtE,QAAM,KAAM,IAAI,QAAQ,IAAI,EAAoB,KAAK;AAErD,QAAM,UAAU,MAAM;AAAA,IACpB;AAAA,IACA;AAAA,IACA,EAAE,IAAI,WAAW,UAAU,MAAM,WAAW,KAAK;AAAA,IACjD,CAAC;AAAA,IACD,EAAE,UAAU,eAAe;AAAA,EAC7B;AAEA,MAAI,CAAC,QAAS;AAEd,QAAM,YAAY,kBAAkB;AACpC,QAAM,YAAY,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAC9C,QAAM,OAAO,KAAK,UAAU;AAAA,IAC1B,MAAM;AAAA,IACN,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,MAAM;AAAA,EACR,CAAC;AAED,QAAM,MAAM,oBAAI,KAAK;AACrB,QAAM,WAAW,GAAG,OAAO,uBAAuB;AAAA,IAChD,WAAW,QAAQ;AAAA,IACnB,WAAW;AAAA,IACX;AAAA,IACA,SAAS,KAAK,MAAM,IAAI;AAAA,IACxB,QAAQ;AAAA,IACR,eAAe;AAAA,IACf,aAAa,QAAQ;AAAA,IACrB,WAAW,QAAQ;AAAA,IACnB,gBAAgB,QAAQ;AAAA,IACxB,UAAU,QAAQ;AAAA,IAClB,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,WAAW;AAAA,EACb,CAAC;AAED,QAAM,GAAG,MAAM;AAEf,QAAM,UAAU;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AAEA,QAAM,YAAY,KAAK,IAAI;AAE3B,MAAI;AACF,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,QAAQ,SAAS;AAExE,UAAM,WAAW,MAAM,MAAM,QAAQ,KAAK;AAAA,MACxC,QAAQ,QAAQ;AAAA,MAChB,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,GAAG;AAAA,QACH,GAAI,QAAQ,iBAAiB,CAAC;AAAA,MAChC;AAAA,MACA;AAAA,MACA,QAAQ,WAAW;AAAA,IACrB,CAAC;AAED,iBAAa,SAAS;AAEtB,UAAM,aAAa,KAAK,IAAI,IAAI;AAChC,UAAM,eAAe,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE;AAEzD,aAAS,iBAAiB,SAAS;AACnC,aAAS,eAAe,aAAa,MAAM,GAAG,IAAI;AAClD,aAAS,aAAa;AACtB,aAAS,gBAAgB,oBAAI,KAAK;AAClC,aAAS,iBAAiB;AAE1B,QAAI,SAAS,IAAI;AACf,eAAS,SAAS;AAClB,eAAS,cAAc,oBAAI,KAAK;AAChC,cAAQ,sBAAsB;AAC9B,cAAQ,gBAAgB,oBAAI,KAAK;AAAA,IACnC,OAAO;AACL,YAAM,cAAc,kBAAkB,SAAS,MAAM,KAAK,SAAS,gBAAgB,SAAS;AAC5F,UAAI,aAAa;AACf,iBAAS,SAAS;AAClB,iBAAS,cAAc,mBAAmB,SAAS,aAAa;AAAA,MAClE,OAAO;AACL,iBAAS,SAAS;AAAA,MACpB;AACA,cAAQ,uBAAuB;AAC/B,cAAQ,gBAAgB,oBAAI,KAAK;AAEjC,UAAI,QAAQ,uBAAuB,KAAK,QAAQ,uBAAuB,QAAQ,sBAAsB;AACnG,gBAAQ,WAAW;AAAA,MACrB;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,UAAM,aAAa,KAAK,IAAI,IAAI;AAChC,aAAS,aAAa;AACtB,aAAS,gBAAgB,oBAAI,KAAK;AAClC,aAAS,iBAAiB;AAC1B,aAAS,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAEjE,UAAM,cAAc,SAAS,gBAAgB,SAAS;AACtD,QAAI,aAAa;AACf,eAAS,SAAS;AAClB,eAAS,cAAc,mBAAmB,SAAS,aAAa;AAAA,IAClE,OAAO;AACL,eAAS,SAAS;AAAA,IACpB;AAEA,YAAQ,uBAAuB;AAC/B,YAAQ,gBAAgB,oBAAI,KAAK;AAEjC,QAAI,QAAQ,uBAAuB,KAAK,QAAQ,uBAAuB,QAAQ,sBAAsB;AACnG,cAAQ,WAAW;AAAA,IACrB;AAAA,EACF;AAEA,QAAM,GAAG,MAAM;AACjB;AAEA,SAAS,kBAAkB,QAAyB;AAClD,MAAI,UAAU,OAAO,SAAS,IAAK,QAAO;AAC1C,MAAI,WAAW,OAAO,WAAW,IAAK,QAAO;AAC7C,MAAI,UAAU,IAAK,QAAO;AAC1B,SAAO;AACT;AAEA,SAAS,mBAAmB,eAA6B;AACvD,QAAM,YAAY;AAClB,QAAM,UAAU,YAAY,KAAK,IAAI,GAAG,gBAAgB,CAAC;AACzD,QAAM,SAAS,KAAK,OAAO,IAAI;AAC/B,SAAO,IAAI,KAAK,KAAK,IAAI,IAAI,UAAU,MAAM;AAC/C;",
6
+ "names": []
7
+ }