@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.
Files changed (35) hide show
  1. package/README.md +62 -5
  2. package/dist/database/schema.cjs +4 -6
  3. package/dist/database/schema.d.cts +6 -2
  4. package/dist/database/schema.d.mts +6 -2
  5. package/dist/database/schema.d.ts +6 -2
  6. package/dist/database/schema.mjs +5 -3
  7. package/dist/export/worker.cjs +290 -66
  8. package/dist/export/worker.d.cts +22 -3
  9. package/dist/export/worker.d.mts +22 -3
  10. package/dist/export/worker.d.ts +22 -3
  11. package/dist/export/worker.mjs +282 -58
  12. package/dist/export/wrangler.cjs +19 -1
  13. package/dist/export/wrangler.d.cts +5 -1
  14. package/dist/export/wrangler.d.mts +5 -1
  15. package/dist/export/wrangler.d.ts +5 -1
  16. package/dist/export/wrangler.mjs +19 -1
  17. package/dist/shared/{notification.B0pktSz9.cjs → notification.BLPB8Ib2.cjs} +79 -0
  18. package/dist/shared/{notification.DWuoMDHY.d.ts → notification.BiG4Q650.d.cts} +98 -6
  19. package/dist/shared/{notification.B4ZLWDCP.d.cts → notification.BiG4Q650.d.mts} +98 -6
  20. package/dist/shared/{notification.CpFoKjoN.d.mts → notification.BiG4Q650.d.ts} +98 -6
  21. package/dist/shared/{notification.CmITLO7E.mjs → notification.CP_hFlNt.mjs} +75 -1
  22. package/dist/shared/{notification.BB9Jl8DI.d.mts → notification.CdlaOUd0.d.cts} +3 -0
  23. package/dist/shared/{notification.BB9Jl8DI.d.ts → notification.CdlaOUd0.d.mts} +3 -0
  24. package/dist/shared/{notification.BB9Jl8DI.d.cts → notification.CdlaOUd0.d.ts} +3 -0
  25. package/dist/types.cjs +19 -19
  26. package/dist/types.d.cts +5 -16
  27. package/dist/types.d.mts +5 -16
  28. package/dist/types.d.ts +5 -16
  29. package/dist/types.mjs +2 -10
  30. package/package.json +3 -3
  31. package/dist/shared/notification.4b3eUEIG.cjs +0 -22
  32. package/dist/shared/notification.BWLPh6Gb.d.cts +0 -140
  33. package/dist/shared/notification.BWLPh6Gb.d.mts +0 -140
  34. package/dist/shared/notification.BWLPh6Gb.d.ts +0 -140
  35. package/dist/shared/notification.C0X8Orrh.mjs +0 -19
@@ -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 { S as SlackConnector, I as IEmailConnector, a as ISmsConnector, t as tables, N as NotificationQueueMessage, b as SendEmailInput, c as SendEmailOutput, d as SendSmsInput, e as SendSmsOutput, f as SendSlackInput, g as SendSlackOutput } from '../shared/notification.B4ZLWDCP.cjs';
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
 
@@ -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 { S as SlackConnector, I as IEmailConnector, a as ISmsConnector, t as tables, N as NotificationQueueMessage, b as SendEmailInput, c as SendEmailOutput, d as SendSmsInput, e as SendSmsOutput, f as SendSlackInput, g as SendSlackOutput } from '../shared/notification.CpFoKjoN.mjs';
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
 
@@ -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 { S as SlackConnector, I as IEmailConnector, a as ISmsConnector, t as tables, N as NotificationQueueMessage, b as SendEmailInput, c as SendEmailOutput, d as SendSmsInput, e as SendSmsOutput, f as SendSlackInput, g as SendSlackOutput } from '../shared/notification.DWuoMDHY.js';
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
 
@@ -1,8 +1,9 @@
1
- import { createInternalError, uuidv4, develitWorker, cloudflareQueue, action, service } from '@develit-io/backend-sdk';
2
- import { s as schema } from '../shared/notification.C0X8Orrh.mjs';
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, a as sendSmsInputSchema, b as sendSlackInputSchema } from '../shared/notification.CmITLO7E.mjs';
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
- const createAuditLogCommand = async ({
33
- db,
34
- auditLog: {
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: { service: service2, userId }
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
- const { command } = await createAuditLogCommand({
160
- db: this.db,
161
- auditLog: {
162
- id: uuidv4(),
163
- event: "EMAIL",
164
- ip,
165
- initiatorService: service2,
166
- initiatorUserId: userId,
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
- description: JSON.stringify(input)
169
- }
170
- });
171
- await this.db.batch([command]);
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: { service: service2, userId }
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
- const { command } = await createAuditLogCommand({
205
- db: this.db,
206
- auditLog: {
207
- id: uuidv4(),
208
- event: "SMS",
209
- ip,
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
- initiatorService: service2,
212
- initiatorUserId: userId,
213
- description: JSON.stringify(input)
214
- }
215
- });
216
- await this.db.batch([command]);
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("public-send-email")
523
+ action("send-email")
315
524
  ], NotificationServiceBase.prototype, "sendEmail", 1);
316
525
  __decorateClass([
317
- action("public-send-email-sync")
526
+ action("send-email-sync")
318
527
  ], NotificationServiceBase.prototype, "sendEmailSync", 1);
319
528
  __decorateClass([
320
- action("public-send-sms")
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);
@@ -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.BB9Jl8DI.cjs';
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.BB9Jl8DI.mjs';
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.BB9Jl8DI.js';
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;