@develit-services/notification 0.5.1 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -5
- package/dist/database/schema.cjs +4 -6
- package/dist/database/schema.d.cts +6 -2
- package/dist/database/schema.d.mts +6 -2
- package/dist/database/schema.d.ts +6 -2
- package/dist/database/schema.mjs +5 -3
- package/dist/export/worker.cjs +290 -66
- package/dist/export/worker.d.cts +22 -3
- package/dist/export/worker.d.mts +22 -3
- package/dist/export/worker.d.ts +22 -3
- package/dist/export/worker.mjs +282 -58
- package/dist/export/wrangler.cjs +19 -1
- package/dist/export/wrangler.d.cts +5 -1
- package/dist/export/wrangler.d.mts +5 -1
- package/dist/export/wrangler.d.ts +5 -1
- package/dist/export/wrangler.mjs +19 -1
- package/dist/shared/{notification.B0pktSz9.cjs → notification.BLPB8Ib2.cjs} +79 -0
- package/dist/shared/{notification.DWuoMDHY.d.ts → notification.BiG4Q650.d.cts} +98 -6
- package/dist/shared/{notification.B4ZLWDCP.d.cts → notification.BiG4Q650.d.mts} +98 -6
- package/dist/shared/{notification.CpFoKjoN.d.mts → notification.BiG4Q650.d.ts} +98 -6
- package/dist/shared/{notification.CmITLO7E.mjs → notification.CP_hFlNt.mjs} +75 -1
- package/dist/shared/{notification.BB9Jl8DI.d.mts → notification.CdlaOUd0.d.cts} +3 -0
- package/dist/shared/{notification.BB9Jl8DI.d.ts → notification.CdlaOUd0.d.mts} +3 -0
- package/dist/shared/{notification.BB9Jl8DI.d.cts → notification.CdlaOUd0.d.ts} +3 -0
- package/dist/types.cjs +19 -19
- package/dist/types.d.cts +5 -16
- package/dist/types.d.mts +5 -16
- package/dist/types.d.ts +5 -16
- package/dist/types.mjs +2 -10
- package/package.json +3 -3
- package/dist/shared/notification.4b3eUEIG.cjs +0 -22
- package/dist/shared/notification.BWLPh6Gb.d.cts +0 -140
- package/dist/shared/notification.BWLPh6Gb.d.mts +0 -140
- package/dist/shared/notification.BWLPh6Gb.d.ts +0 -140
- package/dist/shared/notification.C0X8Orrh.mjs +0 -19
package/dist/export/worker.d.cts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import * as _develit_io_backend_sdk from '@develit-io/backend-sdk';
|
|
2
2
|
import { IRPCResponse } from '@develit-io/backend-sdk';
|
|
3
|
-
import {
|
|
3
|
+
import { s as schema } from '../database/schema.cjs';
|
|
4
|
+
import { S as SlackConnector, W as WebhookConnector, I as IEmailConnector, a as ISmsConnector, N as NotificationQueueMessage, b as SendEmailInput, c as SendEmailOutput, d as SendSmsInput, e as SendSmsOutput, f as SendSlackInput, g as SendSlackOutput, h as SendWebhookInput, i as SendWebhookOutput, G as GetReceivedEmailsInput, j as GetReceivedEmailsOutput, k as WaitForEmailInput, l as WaitForEmailOutput, C as ClearReceivedEmailsInput, m as ClearReceivedEmailsOutput } from '../shared/notification.BiG4Q650.cjs';
|
|
4
5
|
import { WorkerEntrypoint } from 'cloudflare:workers';
|
|
5
6
|
import { DrizzleD1Database } from 'drizzle-orm/d1';
|
|
6
|
-
import '../shared/notification.BWLPh6Gb.cjs';
|
|
7
|
-
import 'drizzle-orm/sqlite-core';
|
|
8
7
|
import 'zod';
|
|
9
8
|
import 'zod/v4';
|
|
10
9
|
|
|
10
|
+
declare const tables: typeof schema;
|
|
11
|
+
|
|
11
12
|
declare const NotificationServiceBase_base: (abstract new (ctx: ExecutionContext, env: NotificationEnv) => WorkerEntrypoint<NotificationEnv, {}>) & (abstract new (...args: any[]) => _develit_io_backend_sdk.DevelitWorkerMethods);
|
|
12
13
|
declare class NotificationServiceBase extends NotificationServiceBase_base {
|
|
13
14
|
readonly slackConnector: SlackConnector;
|
|
15
|
+
protected webhookConnector: WebhookConnector;
|
|
14
16
|
protected emailConnector: IEmailConnector;
|
|
15
17
|
protected smsConnector: ISmsConnector;
|
|
16
18
|
readonly db: DrizzleD1Database<typeof tables>;
|
|
@@ -23,6 +25,23 @@ declare class NotificationServiceBase extends NotificationServiceBase_base {
|
|
|
23
25
|
sendSms(input: SendSmsInput): Promise<IRPCResponse<SendSmsOutput>>;
|
|
24
26
|
protected _sendPushNotification(): Promise<IRPCResponse<{}>>;
|
|
25
27
|
sendSlackNotification(input: SendSlackInput): Promise<IRPCResponse<SendSlackOutput>>;
|
|
28
|
+
sendWebhook(input: SendWebhookInput): Promise<IRPCResponse<SendWebhookOutput>>;
|
|
29
|
+
protected _sendWebhook(input: SendWebhookInput): Promise<IRPCResponse<SendWebhookOutput>>;
|
|
30
|
+
/**
|
|
31
|
+
* Get received emails from KV storage
|
|
32
|
+
* Used primarily for E2E testing
|
|
33
|
+
*/
|
|
34
|
+
getReceivedEmails(input: GetReceivedEmailsInput): Promise<IRPCResponse<GetReceivedEmailsOutput>>;
|
|
35
|
+
/**
|
|
36
|
+
* Wait for an email to arrive (polling helper for E2E tests)
|
|
37
|
+
* NOTE: Limited to 5 second timeout to prevent blocking
|
|
38
|
+
*/
|
|
39
|
+
waitForEmail(input: WaitForEmailInput): Promise<IRPCResponse<WaitForEmailOutput>>;
|
|
40
|
+
/**
|
|
41
|
+
* Clear received emails for a recipient (cleanup helper)
|
|
42
|
+
* Used primarily for E2E testing
|
|
43
|
+
*/
|
|
44
|
+
clearReceivedEmails(input: ClearReceivedEmailsInput): Promise<IRPCResponse<ClearReceivedEmailsOutput>>;
|
|
26
45
|
}
|
|
27
46
|
declare function defineNotificationService(): new (ctx: ExecutionContext, env: NotificationEnv) => NotificationServiceBase;
|
|
28
47
|
|
package/dist/export/worker.d.mts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import * as _develit_io_backend_sdk from '@develit-io/backend-sdk';
|
|
2
2
|
import { IRPCResponse } from '@develit-io/backend-sdk';
|
|
3
|
-
import {
|
|
3
|
+
import { s as schema } from '../database/schema.mjs';
|
|
4
|
+
import { S as SlackConnector, W as WebhookConnector, I as IEmailConnector, a as ISmsConnector, N as NotificationQueueMessage, b as SendEmailInput, c as SendEmailOutput, d as SendSmsInput, e as SendSmsOutput, f as SendSlackInput, g as SendSlackOutput, h as SendWebhookInput, i as SendWebhookOutput, G as GetReceivedEmailsInput, j as GetReceivedEmailsOutput, k as WaitForEmailInput, l as WaitForEmailOutput, C as ClearReceivedEmailsInput, m as ClearReceivedEmailsOutput } from '../shared/notification.BiG4Q650.mjs';
|
|
4
5
|
import { WorkerEntrypoint } from 'cloudflare:workers';
|
|
5
6
|
import { DrizzleD1Database } from 'drizzle-orm/d1';
|
|
6
|
-
import '../shared/notification.BWLPh6Gb.mjs';
|
|
7
|
-
import 'drizzle-orm/sqlite-core';
|
|
8
7
|
import 'zod';
|
|
9
8
|
import 'zod/v4';
|
|
10
9
|
|
|
10
|
+
declare const tables: typeof schema;
|
|
11
|
+
|
|
11
12
|
declare const NotificationServiceBase_base: (abstract new (ctx: ExecutionContext, env: NotificationEnv) => WorkerEntrypoint<NotificationEnv, {}>) & (abstract new (...args: any[]) => _develit_io_backend_sdk.DevelitWorkerMethods);
|
|
12
13
|
declare class NotificationServiceBase extends NotificationServiceBase_base {
|
|
13
14
|
readonly slackConnector: SlackConnector;
|
|
15
|
+
protected webhookConnector: WebhookConnector;
|
|
14
16
|
protected emailConnector: IEmailConnector;
|
|
15
17
|
protected smsConnector: ISmsConnector;
|
|
16
18
|
readonly db: DrizzleD1Database<typeof tables>;
|
|
@@ -23,6 +25,23 @@ declare class NotificationServiceBase extends NotificationServiceBase_base {
|
|
|
23
25
|
sendSms(input: SendSmsInput): Promise<IRPCResponse<SendSmsOutput>>;
|
|
24
26
|
protected _sendPushNotification(): Promise<IRPCResponse<{}>>;
|
|
25
27
|
sendSlackNotification(input: SendSlackInput): Promise<IRPCResponse<SendSlackOutput>>;
|
|
28
|
+
sendWebhook(input: SendWebhookInput): Promise<IRPCResponse<SendWebhookOutput>>;
|
|
29
|
+
protected _sendWebhook(input: SendWebhookInput): Promise<IRPCResponse<SendWebhookOutput>>;
|
|
30
|
+
/**
|
|
31
|
+
* Get received emails from KV storage
|
|
32
|
+
* Used primarily for E2E testing
|
|
33
|
+
*/
|
|
34
|
+
getReceivedEmails(input: GetReceivedEmailsInput): Promise<IRPCResponse<GetReceivedEmailsOutput>>;
|
|
35
|
+
/**
|
|
36
|
+
* Wait for an email to arrive (polling helper for E2E tests)
|
|
37
|
+
* NOTE: Limited to 5 second timeout to prevent blocking
|
|
38
|
+
*/
|
|
39
|
+
waitForEmail(input: WaitForEmailInput): Promise<IRPCResponse<WaitForEmailOutput>>;
|
|
40
|
+
/**
|
|
41
|
+
* Clear received emails for a recipient (cleanup helper)
|
|
42
|
+
* Used primarily for E2E testing
|
|
43
|
+
*/
|
|
44
|
+
clearReceivedEmails(input: ClearReceivedEmailsInput): Promise<IRPCResponse<ClearReceivedEmailsOutput>>;
|
|
26
45
|
}
|
|
27
46
|
declare function defineNotificationService(): new (ctx: ExecutionContext, env: NotificationEnv) => NotificationServiceBase;
|
|
28
47
|
|
package/dist/export/worker.d.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import * as _develit_io_backend_sdk from '@develit-io/backend-sdk';
|
|
2
2
|
import { IRPCResponse } from '@develit-io/backend-sdk';
|
|
3
|
-
import {
|
|
3
|
+
import { s as schema } from '../database/schema.js';
|
|
4
|
+
import { S as SlackConnector, W as WebhookConnector, I as IEmailConnector, a as ISmsConnector, N as NotificationQueueMessage, b as SendEmailInput, c as SendEmailOutput, d as SendSmsInput, e as SendSmsOutput, f as SendSlackInput, g as SendSlackOutput, h as SendWebhookInput, i as SendWebhookOutput, G as GetReceivedEmailsInput, j as GetReceivedEmailsOutput, k as WaitForEmailInput, l as WaitForEmailOutput, C as ClearReceivedEmailsInput, m as ClearReceivedEmailsOutput } from '../shared/notification.BiG4Q650.js';
|
|
4
5
|
import { WorkerEntrypoint } from 'cloudflare:workers';
|
|
5
6
|
import { DrizzleD1Database } from 'drizzle-orm/d1';
|
|
6
|
-
import '../shared/notification.BWLPh6Gb.js';
|
|
7
|
-
import 'drizzle-orm/sqlite-core';
|
|
8
7
|
import 'zod';
|
|
9
8
|
import 'zod/v4';
|
|
10
9
|
|
|
10
|
+
declare const tables: typeof schema;
|
|
11
|
+
|
|
11
12
|
declare const NotificationServiceBase_base: (abstract new (ctx: ExecutionContext, env: NotificationEnv) => WorkerEntrypoint<NotificationEnv, {}>) & (abstract new (...args: any[]) => _develit_io_backend_sdk.DevelitWorkerMethods);
|
|
12
13
|
declare class NotificationServiceBase extends NotificationServiceBase_base {
|
|
13
14
|
readonly slackConnector: SlackConnector;
|
|
15
|
+
protected webhookConnector: WebhookConnector;
|
|
14
16
|
protected emailConnector: IEmailConnector;
|
|
15
17
|
protected smsConnector: ISmsConnector;
|
|
16
18
|
readonly db: DrizzleD1Database<typeof tables>;
|
|
@@ -23,6 +25,23 @@ declare class NotificationServiceBase extends NotificationServiceBase_base {
|
|
|
23
25
|
sendSms(input: SendSmsInput): Promise<IRPCResponse<SendSmsOutput>>;
|
|
24
26
|
protected _sendPushNotification(): Promise<IRPCResponse<{}>>;
|
|
25
27
|
sendSlackNotification(input: SendSlackInput): Promise<IRPCResponse<SendSlackOutput>>;
|
|
28
|
+
sendWebhook(input: SendWebhookInput): Promise<IRPCResponse<SendWebhookOutput>>;
|
|
29
|
+
protected _sendWebhook(input: SendWebhookInput): Promise<IRPCResponse<SendWebhookOutput>>;
|
|
30
|
+
/**
|
|
31
|
+
* Get received emails from KV storage
|
|
32
|
+
* Used primarily for E2E testing
|
|
33
|
+
*/
|
|
34
|
+
getReceivedEmails(input: GetReceivedEmailsInput): Promise<IRPCResponse<GetReceivedEmailsOutput>>;
|
|
35
|
+
/**
|
|
36
|
+
* Wait for an email to arrive (polling helper for E2E tests)
|
|
37
|
+
* NOTE: Limited to 5 second timeout to prevent blocking
|
|
38
|
+
*/
|
|
39
|
+
waitForEmail(input: WaitForEmailInput): Promise<IRPCResponse<WaitForEmailOutput>>;
|
|
40
|
+
/**
|
|
41
|
+
* Clear received emails for a recipient (cleanup helper)
|
|
42
|
+
* Used primarily for E2E testing
|
|
43
|
+
*/
|
|
44
|
+
clearReceivedEmails(input: ClearReceivedEmailsInput): Promise<IRPCResponse<ClearReceivedEmailsOutput>>;
|
|
26
45
|
}
|
|
27
46
|
declare function defineNotificationService(): new (ctx: ExecutionContext, env: NotificationEnv) => NotificationServiceBase;
|
|
28
47
|
|
package/dist/export/worker.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { createInternalError,
|
|
2
|
-
import { s as schema } from '../
|
|
1
|
+
import { createInternalError, develitWorker, uuidv4, cloudflareQueue, action, service } from '@develit-io/backend-sdk';
|
|
2
|
+
import { s as schema } from '../database/schema.mjs';
|
|
3
3
|
import 'drizzle-orm';
|
|
4
4
|
import 'drizzle-orm/sqlite-core';
|
|
5
|
-
import { E as EcomailConnector, T as TwilioConnector, S as SlackConnector, s as sendEmailInputSchema,
|
|
5
|
+
import { E as EcomailConnector, T as TwilioConnector, S as SlackConnector, s as sendEmailInputSchema, f as sendSmsInputSchema, e as sendSlackInputSchema, h as sendWebhookInputSchema, W as WebhookConnector, g as getReceivedEmailsInputSchema, w as waitForEmailInputSchema, c as clearReceivedEmailsInputSchema } from '../shared/notification.CP_hFlNt.mjs';
|
|
6
|
+
import '@develit-io/backend-sdk/signature';
|
|
6
7
|
import { WorkerEntrypoint } from 'cloudflare:workers';
|
|
7
8
|
import { drizzle } from 'drizzle-orm/d1';
|
|
8
9
|
import 'zod';
|
|
@@ -29,31 +30,9 @@ const initiateEmailConnector = async (provider, apiKey, smtpHost, senderEmail, s
|
|
|
29
30
|
});
|
|
30
31
|
};
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
event,
|
|
36
|
-
description,
|
|
37
|
-
initiatorService,
|
|
38
|
-
initiatorUserId,
|
|
39
|
-
ip,
|
|
40
|
-
userAgent
|
|
41
|
-
}
|
|
42
|
-
}) => {
|
|
43
|
-
const command = db.insert(tables.auditLog).values({
|
|
44
|
-
id: uuidv4(),
|
|
45
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
46
|
-
event,
|
|
47
|
-
description,
|
|
48
|
-
ip,
|
|
49
|
-
userAgent,
|
|
50
|
-
initiatorService,
|
|
51
|
-
initiatorUserId
|
|
52
|
-
});
|
|
53
|
-
return {
|
|
54
|
-
command
|
|
55
|
-
};
|
|
56
|
-
};
|
|
33
|
+
function generateEmailKVPattern(recipient) {
|
|
34
|
+
return `email:${recipient}:`;
|
|
35
|
+
}
|
|
57
36
|
|
|
58
37
|
const initiateSmsConnector = async (provider, accountId, authToken, serviceId) => {
|
|
59
38
|
const connector = [TwilioConnector].find(
|
|
@@ -117,6 +96,12 @@ let NotificationServiceBase = class extends develitWorker(
|
|
|
117
96
|
metadata
|
|
118
97
|
});
|
|
119
98
|
break;
|
|
99
|
+
case "webhook":
|
|
100
|
+
notificationAction = async () => this._sendWebhook({
|
|
101
|
+
webhook: payload.webhook,
|
|
102
|
+
metadata
|
|
103
|
+
});
|
|
104
|
+
break;
|
|
120
105
|
default:
|
|
121
106
|
this.logError({ error: `Unknown notification type: ${type}` });
|
|
122
107
|
message.retry();
|
|
@@ -141,7 +126,7 @@ let NotificationServiceBase = class extends develitWorker(
|
|
|
141
126
|
metadata: {
|
|
142
127
|
ip,
|
|
143
128
|
userAgent,
|
|
144
|
-
initiator: {
|
|
129
|
+
initiator: { userId }
|
|
145
130
|
}
|
|
146
131
|
} = params;
|
|
147
132
|
if (!this.emailConnector) {
|
|
@@ -156,19 +141,28 @@ let NotificationServiceBase = class extends develitWorker(
|
|
|
156
141
|
);
|
|
157
142
|
}
|
|
158
143
|
await this.emailConnector.sendEmail(email);
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
144
|
+
try {
|
|
145
|
+
await this.pushToQueue(this.env.AUDIT_LOGS_QUEUE, {
|
|
146
|
+
logType: "event",
|
|
147
|
+
service: "notification",
|
|
148
|
+
correlationId: uuidv4(),
|
|
149
|
+
eventType: "notification.email_sent",
|
|
150
|
+
actorUserId: userId,
|
|
151
|
+
actorEmail: userId || "SYSTEM",
|
|
152
|
+
targetType: "email",
|
|
153
|
+
targetId: email.to,
|
|
154
|
+
sourceIp: ip,
|
|
167
155
|
userAgent,
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
156
|
+
outcome: "success",
|
|
157
|
+
description: `Email sent to ${email.to}`,
|
|
158
|
+
details: JSON.stringify({
|
|
159
|
+
subject: email.subject,
|
|
160
|
+
templateId: email.templateId
|
|
161
|
+
})
|
|
162
|
+
});
|
|
163
|
+
} catch (e) {
|
|
164
|
+
console.error("Failed to push email audit log", e);
|
|
165
|
+
}
|
|
172
166
|
return {};
|
|
173
167
|
}
|
|
174
168
|
);
|
|
@@ -183,7 +177,7 @@ let NotificationServiceBase = class extends develitWorker(
|
|
|
183
177
|
metadata: {
|
|
184
178
|
ip,
|
|
185
179
|
userAgent,
|
|
186
|
-
initiator: {
|
|
180
|
+
initiator: { userId }
|
|
187
181
|
}
|
|
188
182
|
} = params;
|
|
189
183
|
if (!this.smsConnector) {
|
|
@@ -201,19 +195,25 @@ let NotificationServiceBase = class extends develitWorker(
|
|
|
201
195
|
);
|
|
202
196
|
}
|
|
203
197
|
await this.smsConnector.sendSms({ message, to });
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
198
|
+
try {
|
|
199
|
+
await this.pushToQueue(this.env.AUDIT_LOGS_QUEUE, {
|
|
200
|
+
logType: "event",
|
|
201
|
+
service: "notification",
|
|
202
|
+
correlationId: uuidv4(),
|
|
203
|
+
eventType: "notification.sms_sent",
|
|
204
|
+
actorUserId: userId,
|
|
205
|
+
actorEmail: userId || "SYSTEM",
|
|
206
|
+
targetType: "sms",
|
|
207
|
+
targetId: to,
|
|
208
|
+
sourceIp: ip,
|
|
210
209
|
userAgent,
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
})
|
|
216
|
-
|
|
210
|
+
outcome: "success",
|
|
211
|
+
description: `SMS sent to ${to}`,
|
|
212
|
+
details: JSON.stringify({ message })
|
|
213
|
+
});
|
|
214
|
+
} catch (e) {
|
|
215
|
+
console.error("Failed to push sms audit log", e);
|
|
216
|
+
}
|
|
217
217
|
return {};
|
|
218
218
|
}
|
|
219
219
|
);
|
|
@@ -294,12 +294,221 @@ let NotificationServiceBase = class extends develitWorker(
|
|
|
294
294
|
},
|
|
295
295
|
{ successMessage: "Slack sent." },
|
|
296
296
|
async (params) => {
|
|
297
|
-
const { slack } = params;
|
|
297
|
+
const { slack, metadata } = params;
|
|
298
298
|
await this.slackConnector.sendNotificationToAllSlack(slack.message);
|
|
299
|
+
await this.pushToQueue(this.env.AUDIT_LOGS_QUEUE, {
|
|
300
|
+
logType: "event",
|
|
301
|
+
service: "notification",
|
|
302
|
+
correlationId: uuidv4(),
|
|
303
|
+
eventType: "notification.slack_sent",
|
|
304
|
+
actorUserId: metadata?.initiator?.userId,
|
|
305
|
+
actorEmail: metadata?.initiator?.userId || "SYSTEM",
|
|
306
|
+
targetType: "slack",
|
|
307
|
+
targetId: "all-channels",
|
|
308
|
+
sourceIp: metadata?.ip,
|
|
309
|
+
userAgent: metadata?.userAgent,
|
|
310
|
+
outcome: "success",
|
|
311
|
+
description: "Slack notification sent",
|
|
312
|
+
details: JSON.stringify({
|
|
313
|
+
message: slack.message
|
|
314
|
+
})
|
|
315
|
+
});
|
|
316
|
+
return {};
|
|
317
|
+
}
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
async sendWebhook(input) {
|
|
321
|
+
return this.handleAction(
|
|
322
|
+
{ data: input, schema: sendWebhookInputSchema },
|
|
323
|
+
{ successMessage: "Webhook queued." },
|
|
324
|
+
async (params) => {
|
|
325
|
+
const { webhook, metadata } = params;
|
|
326
|
+
await this.pushToQueue(
|
|
327
|
+
this.env.NOTIFICATIONS_QUEUE,
|
|
328
|
+
{
|
|
329
|
+
type: "webhook",
|
|
330
|
+
payload: {
|
|
331
|
+
webhook
|
|
332
|
+
},
|
|
333
|
+
metadata
|
|
334
|
+
}
|
|
335
|
+
);
|
|
336
|
+
return {};
|
|
337
|
+
}
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
async _sendWebhook(input) {
|
|
341
|
+
return this.handleAction(
|
|
342
|
+
{ data: input, schema: sendWebhookInputSchema },
|
|
343
|
+
{ successMessage: "Webhook sent." },
|
|
344
|
+
async (params) => {
|
|
345
|
+
const {
|
|
346
|
+
webhook,
|
|
347
|
+
metadata: {
|
|
348
|
+
ip,
|
|
349
|
+
userAgent,
|
|
350
|
+
initiator: { userId }
|
|
351
|
+
}
|
|
352
|
+
} = params;
|
|
353
|
+
if (!this.webhookConnector) {
|
|
354
|
+
const privateKey = (await this.env.SECRETS_STORE.get({
|
|
355
|
+
secretName: "NOTIFICATION_SERVICE_WEBHOOK_SIGNING_KEY"
|
|
356
|
+
})).data?.secretValue;
|
|
357
|
+
if (!privateKey) {
|
|
358
|
+
throw createInternalError(null, {
|
|
359
|
+
message: "NOTIFICATION_SERVICE_WEBHOOK_SIGNING_KEY is not configured",
|
|
360
|
+
code: "SYS-N-02",
|
|
361
|
+
status: 500
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
this.webhookConnector = new WebhookConnector(privateKey);
|
|
365
|
+
}
|
|
366
|
+
await this.webhookConnector.sendWebhook(webhook);
|
|
367
|
+
try {
|
|
368
|
+
await this.pushToQueue(this.env.AUDIT_LOGS_QUEUE, {
|
|
369
|
+
logType: "event",
|
|
370
|
+
service: "notification",
|
|
371
|
+
correlationId: uuidv4(),
|
|
372
|
+
eventType: "notification.webhook_sent",
|
|
373
|
+
actorUserId: userId,
|
|
374
|
+
actorEmail: userId || "SYSTEM",
|
|
375
|
+
targetType: "webhook",
|
|
376
|
+
targetId: webhook.url,
|
|
377
|
+
sourceIp: ip,
|
|
378
|
+
userAgent,
|
|
379
|
+
outcome: "success",
|
|
380
|
+
description: `Webhook sent to ${webhook.url}`,
|
|
381
|
+
details: JSON.stringify({
|
|
382
|
+
url: webhook.url
|
|
383
|
+
})
|
|
384
|
+
});
|
|
385
|
+
} catch (e) {
|
|
386
|
+
console.error("Failed to push webhook audit log", e);
|
|
387
|
+
}
|
|
299
388
|
return {};
|
|
300
389
|
}
|
|
301
390
|
);
|
|
302
391
|
}
|
|
392
|
+
async getReceivedEmails(input) {
|
|
393
|
+
return this.handleAction(
|
|
394
|
+
{
|
|
395
|
+
data: input,
|
|
396
|
+
schema: getReceivedEmailsInputSchema
|
|
397
|
+
},
|
|
398
|
+
{ successMessage: "Emails retrieved." },
|
|
399
|
+
async (params) => {
|
|
400
|
+
const { recipient, limit, includeContent } = params;
|
|
401
|
+
if (!this.env.RECEIVED_EMAILS_KV) {
|
|
402
|
+
throw new Error("RECEIVED_EMAILS_KV binding is not configured");
|
|
403
|
+
}
|
|
404
|
+
const pattern = generateEmailKVPattern(recipient);
|
|
405
|
+
const list = await this.env.RECEIVED_EMAILS_KV.list({
|
|
406
|
+
prefix: pattern,
|
|
407
|
+
limit
|
|
408
|
+
});
|
|
409
|
+
const emails = [];
|
|
410
|
+
for (const key of list.keys) {
|
|
411
|
+
const emailData = await this.env.RECEIVED_EMAILS_KV.get(
|
|
412
|
+
key.name,
|
|
413
|
+
"json"
|
|
414
|
+
);
|
|
415
|
+
if (emailData) {
|
|
416
|
+
const email = emailData;
|
|
417
|
+
if (!includeContent) {
|
|
418
|
+
delete email.text;
|
|
419
|
+
delete email.html;
|
|
420
|
+
delete email.raw;
|
|
421
|
+
}
|
|
422
|
+
emails.push(email);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
emails.sort(
|
|
426
|
+
(a, b) => new Date(b.receivedAt).getTime() - new Date(a.receivedAt).getTime()
|
|
427
|
+
);
|
|
428
|
+
return {
|
|
429
|
+
emails,
|
|
430
|
+
count: emails.length
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
async waitForEmail(input) {
|
|
436
|
+
return this.handleAction(
|
|
437
|
+
{
|
|
438
|
+
data: input,
|
|
439
|
+
schema: waitForEmailInputSchema
|
|
440
|
+
},
|
|
441
|
+
{ successMessage: "Email check completed." },
|
|
442
|
+
async (params) => {
|
|
443
|
+
const { recipient, subject, timeout, pollInterval } = params;
|
|
444
|
+
if (!this.env.RECEIVED_EMAILS_KV) {
|
|
445
|
+
throw new Error("RECEIVED_EMAILS_KV binding is not configured");
|
|
446
|
+
}
|
|
447
|
+
const maxTimeout = Math.min(timeout || 5e3, 5e3);
|
|
448
|
+
const safeInterval = Math.max(pollInterval || 500, 100);
|
|
449
|
+
const startTime = Date.now();
|
|
450
|
+
const maxIterations = Math.ceil(maxTimeout / safeInterval);
|
|
451
|
+
let iterations = 0;
|
|
452
|
+
while (Date.now() - startTime < maxTimeout && iterations < maxIterations) {
|
|
453
|
+
const pattern = generateEmailKVPattern(recipient);
|
|
454
|
+
const list = await this.env.RECEIVED_EMAILS_KV.list({
|
|
455
|
+
prefix: pattern,
|
|
456
|
+
limit: 50
|
|
457
|
+
});
|
|
458
|
+
for (const key of list.keys) {
|
|
459
|
+
const emailData = await this.env.RECEIVED_EMAILS_KV.get(
|
|
460
|
+
key.name,
|
|
461
|
+
"json"
|
|
462
|
+
);
|
|
463
|
+
if (emailData) {
|
|
464
|
+
const email = emailData;
|
|
465
|
+
if (!subject || email.subject.includes(subject)) {
|
|
466
|
+
return {
|
|
467
|
+
email,
|
|
468
|
+
found: true
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
iterations++;
|
|
474
|
+
if (iterations < maxIterations && Date.now() - startTime < maxTimeout - safeInterval) {
|
|
475
|
+
await new Promise((resolve) => setTimeout(resolve, safeInterval));
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
return {
|
|
479
|
+
email: null,
|
|
480
|
+
found: false
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
async clearReceivedEmails(input) {
|
|
486
|
+
return this.handleAction(
|
|
487
|
+
{
|
|
488
|
+
data: input,
|
|
489
|
+
schema: clearReceivedEmailsInputSchema
|
|
490
|
+
},
|
|
491
|
+
{ successMessage: "Emails cleared." },
|
|
492
|
+
async (params) => {
|
|
493
|
+
const { recipient } = params;
|
|
494
|
+
if (!this.env.RECEIVED_EMAILS_KV) {
|
|
495
|
+
throw new Error("RECEIVED_EMAILS_KV binding is not configured");
|
|
496
|
+
}
|
|
497
|
+
const pattern = generateEmailKVPattern(recipient);
|
|
498
|
+
const list = await this.env.RECEIVED_EMAILS_KV.list({
|
|
499
|
+
prefix: pattern
|
|
500
|
+
});
|
|
501
|
+
let deleted = 0;
|
|
502
|
+
for (const key of list.keys) {
|
|
503
|
+
await this.env.RECEIVED_EMAILS_KV.delete(key.name);
|
|
504
|
+
deleted++;
|
|
505
|
+
}
|
|
506
|
+
return {
|
|
507
|
+
deleted
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
);
|
|
511
|
+
}
|
|
303
512
|
};
|
|
304
513
|
__decorateClass([
|
|
305
514
|
cloudflareQueue({ baseDelay: 60 })
|
|
@@ -311,13 +520,13 @@ __decorateClass([
|
|
|
311
520
|
action("private-send-sms")
|
|
312
521
|
], NotificationServiceBase.prototype, "_sendSms", 1);
|
|
313
522
|
__decorateClass([
|
|
314
|
-
action("
|
|
523
|
+
action("send-email")
|
|
315
524
|
], NotificationServiceBase.prototype, "sendEmail", 1);
|
|
316
525
|
__decorateClass([
|
|
317
|
-
action("
|
|
526
|
+
action("send-email-sync")
|
|
318
527
|
], NotificationServiceBase.prototype, "sendEmailSync", 1);
|
|
319
528
|
__decorateClass([
|
|
320
|
-
action("
|
|
529
|
+
action("send-sms")
|
|
321
530
|
], NotificationServiceBase.prototype, "sendSms", 1);
|
|
322
531
|
__decorateClass([
|
|
323
532
|
action("send-push-notification")
|
|
@@ -325,6 +534,21 @@ __decorateClass([
|
|
|
325
534
|
__decorateClass([
|
|
326
535
|
action("send-slack-notification")
|
|
327
536
|
], NotificationServiceBase.prototype, "sendSlackNotification", 1);
|
|
537
|
+
__decorateClass([
|
|
538
|
+
action("send-webhook")
|
|
539
|
+
], NotificationServiceBase.prototype, "sendWebhook", 1);
|
|
540
|
+
__decorateClass([
|
|
541
|
+
action("private-send-webhook")
|
|
542
|
+
], NotificationServiceBase.prototype, "_sendWebhook", 1);
|
|
543
|
+
__decorateClass([
|
|
544
|
+
action("get-received-emails")
|
|
545
|
+
], NotificationServiceBase.prototype, "getReceivedEmails", 1);
|
|
546
|
+
__decorateClass([
|
|
547
|
+
action("wait-for-email")
|
|
548
|
+
], NotificationServiceBase.prototype, "waitForEmail", 1);
|
|
549
|
+
__decorateClass([
|
|
550
|
+
action("clear-received-emails")
|
|
551
|
+
], NotificationServiceBase.prototype, "clearReceivedEmails", 1);
|
|
328
552
|
NotificationServiceBase = __decorateClass([
|
|
329
553
|
service("notification")
|
|
330
554
|
], NotificationServiceBase);
|
package/dist/export/wrangler.cjs
CHANGED
|
@@ -27,11 +27,21 @@ function defineNotificationServiceWrangler(config) {
|
|
|
27
27
|
migrations_dir: "./src/database/migrations"
|
|
28
28
|
}
|
|
29
29
|
],
|
|
30
|
+
kv_namespaces: envs.local.kv ? [
|
|
31
|
+
{
|
|
32
|
+
binding: "RECEIVED_EMAILS_KV",
|
|
33
|
+
id: envs.local.kv.id
|
|
34
|
+
}
|
|
35
|
+
] : [],
|
|
30
36
|
queues: {
|
|
31
37
|
producers: [
|
|
32
38
|
{
|
|
33
39
|
binding: "NOTIFICATIONS_QUEUE",
|
|
34
40
|
queue: `${project}-notifications`
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
binding: "AUDIT_LOGS_QUEUE",
|
|
44
|
+
queue: `${project}-audit-logs`
|
|
35
45
|
}
|
|
36
46
|
],
|
|
37
47
|
consumers: [
|
|
@@ -60,7 +70,15 @@ function defineNotificationServiceWrangler(config) {
|
|
|
60
70
|
database_id: envCfg.d1.id,
|
|
61
71
|
migrations_dir: "./src/database/migrations"
|
|
62
72
|
}
|
|
63
|
-
]
|
|
73
|
+
],
|
|
74
|
+
...envCfg.kv && {
|
|
75
|
+
kv_namespaces: [
|
|
76
|
+
{
|
|
77
|
+
binding: "RECEIVED_EMAILS_KV",
|
|
78
|
+
id: envCfg.kv.id
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
}
|
|
64
82
|
};
|
|
65
83
|
}
|
|
66
84
|
return base;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { N as NotificationServiceWranglerConfig } from '../shared/notification.
|
|
1
|
+
import { N as NotificationServiceWranglerConfig } from '../shared/notification.CdlaOUd0.cjs';
|
|
2
2
|
|
|
3
3
|
declare function defineNotificationServiceWrangler(config: NotificationServiceWranglerConfig): {
|
|
4
4
|
vars: {
|
|
@@ -20,6 +20,10 @@ declare function defineNotificationServiceWrangler(config: NotificationServiceWr
|
|
|
20
20
|
database_id: string;
|
|
21
21
|
migrations_dir: string;
|
|
22
22
|
}[];
|
|
23
|
+
kv_namespaces: {
|
|
24
|
+
binding: string;
|
|
25
|
+
id: string;
|
|
26
|
+
}[];
|
|
23
27
|
queues: {
|
|
24
28
|
producers: {
|
|
25
29
|
binding: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { N as NotificationServiceWranglerConfig } from '../shared/notification.
|
|
1
|
+
import { N as NotificationServiceWranglerConfig } from '../shared/notification.CdlaOUd0.mjs';
|
|
2
2
|
|
|
3
3
|
declare function defineNotificationServiceWrangler(config: NotificationServiceWranglerConfig): {
|
|
4
4
|
vars: {
|
|
@@ -20,6 +20,10 @@ declare function defineNotificationServiceWrangler(config: NotificationServiceWr
|
|
|
20
20
|
database_id: string;
|
|
21
21
|
migrations_dir: string;
|
|
22
22
|
}[];
|
|
23
|
+
kv_namespaces: {
|
|
24
|
+
binding: string;
|
|
25
|
+
id: string;
|
|
26
|
+
}[];
|
|
23
27
|
queues: {
|
|
24
28
|
producers: {
|
|
25
29
|
binding: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { N as NotificationServiceWranglerConfig } from '../shared/notification.
|
|
1
|
+
import { N as NotificationServiceWranglerConfig } from '../shared/notification.CdlaOUd0.js';
|
|
2
2
|
|
|
3
3
|
declare function defineNotificationServiceWrangler(config: NotificationServiceWranglerConfig): {
|
|
4
4
|
vars: {
|
|
@@ -20,6 +20,10 @@ declare function defineNotificationServiceWrangler(config: NotificationServiceWr
|
|
|
20
20
|
database_id: string;
|
|
21
21
|
migrations_dir: string;
|
|
22
22
|
}[];
|
|
23
|
+
kv_namespaces: {
|
|
24
|
+
binding: string;
|
|
25
|
+
id: string;
|
|
26
|
+
}[];
|
|
23
27
|
queues: {
|
|
24
28
|
producers: {
|
|
25
29
|
binding: string;
|