@hogsend/engine 0.0.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 (71) hide show
  1. package/LICENSE +93 -0
  2. package/README.md +18 -0
  3. package/package.json +58 -0
  4. package/src/app.ts +102 -0
  5. package/src/container.ts +172 -0
  6. package/src/env.ts +56 -0
  7. package/src/index.ts +114 -0
  8. package/src/journeys/define-journey.ts +188 -0
  9. package/src/journeys/journey-context.ts +179 -0
  10. package/src/journeys/registry-singleton.ts +21 -0
  11. package/src/journeys/registry.ts +53 -0
  12. package/src/lib/alerting.ts +205 -0
  13. package/src/lib/api-key-hash.ts +19 -0
  14. package/src/lib/auth.ts +39 -0
  15. package/src/lib/backfill.ts +84 -0
  16. package/src/lib/contacts.ts +68 -0
  17. package/src/lib/db.ts +13 -0
  18. package/src/lib/email-service-types.ts +115 -0
  19. package/src/lib/email-stats.ts +33 -0
  20. package/src/lib/email.ts +94 -0
  21. package/src/lib/enrollment-guards.ts +56 -0
  22. package/src/lib/hatchet.ts +20 -0
  23. package/src/lib/html.ts +25 -0
  24. package/src/lib/ingestion.ts +162 -0
  25. package/src/lib/logger.ts +32 -0
  26. package/src/lib/mailer.ts +266 -0
  27. package/src/lib/notifications.ts +61 -0
  28. package/src/lib/posthog.ts +19 -0
  29. package/src/lib/redis.ts +30 -0
  30. package/src/lib/schemas.ts +8 -0
  31. package/src/lib/tracked.ts +175 -0
  32. package/src/lib/tracking-event-names.ts +5 -0
  33. package/src/lib/tracking-events.ts +84 -0
  34. package/src/lib/tracking.ts +78 -0
  35. package/src/middleware/api-key.ts +129 -0
  36. package/src/middleware/audit.ts +47 -0
  37. package/src/middleware/auth.ts +24 -0
  38. package/src/middleware/error-handler.ts +22 -0
  39. package/src/middleware/rate-limit.ts +65 -0
  40. package/src/middleware/request-logger.ts +19 -0
  41. package/src/routes/admin/alerts.ts +347 -0
  42. package/src/routes/admin/api-keys.ts +211 -0
  43. package/src/routes/admin/audit-logs.ts +102 -0
  44. package/src/routes/admin/bulk.ts +503 -0
  45. package/src/routes/admin/contacts.ts +342 -0
  46. package/src/routes/admin/dlq.ts +202 -0
  47. package/src/routes/admin/emails.ts +269 -0
  48. package/src/routes/admin/events.ts +132 -0
  49. package/src/routes/admin/index.ts +36 -0
  50. package/src/routes/admin/journey-logs.ts +117 -0
  51. package/src/routes/admin/journeys.ts +677 -0
  52. package/src/routes/admin/metrics.ts +559 -0
  53. package/src/routes/admin/preferences.ts +165 -0
  54. package/src/routes/admin/timeline.ts +221 -0
  55. package/src/routes/email/index.ts +8 -0
  56. package/src/routes/email/preferences.ts +144 -0
  57. package/src/routes/email/unsubscribe.ts +161 -0
  58. package/src/routes/health.ts +131 -0
  59. package/src/routes/index.ts +32 -0
  60. package/src/routes/ingest.ts +71 -0
  61. package/src/routes/tracking/click.ts +103 -0
  62. package/src/routes/tracking/index.ts +9 -0
  63. package/src/routes/tracking/open.ts +71 -0
  64. package/src/routes/webhooks/index.ts +17 -0
  65. package/src/routes/webhooks/resend.ts +68 -0
  66. package/src/routes/webhooks/sources.ts +97 -0
  67. package/src/webhook-sources/define-webhook-source.ts +34 -0
  68. package/src/worker.ts +64 -0
  69. package/src/workflows/check-alerts.ts +24 -0
  70. package/src/workflows/import-contacts.ts +134 -0
  71. package/src/workflows/send-email.ts +54 -0
@@ -0,0 +1,54 @@
1
+ import { NonRetryableError } from "@hatchet-dev/typescript-sdk/v1/index.js";
2
+ import { createResendClient } from "@hogsend/plugin-resend";
3
+ import { hatchet } from "../lib/hatchet.js";
4
+
5
+ const resend = createResendClient({
6
+ apiKey: process.env.RESEND_API_KEY ?? "",
7
+ });
8
+
9
+ const NON_RETRYABLE_CODES = new Set([
10
+ "validation_error",
11
+ "missing_required_field",
12
+ "invalid_api_key",
13
+ "not_found",
14
+ "restricted_api_key",
15
+ ]);
16
+
17
+ export const sendEmailTask = hatchet.task({
18
+ name: "send-email",
19
+ retries: 3,
20
+ executionTimeout: "30s",
21
+ backoff: { factor: 2, maxSeconds: 30 },
22
+ fn: async (input: {
23
+ to: string;
24
+ subject: string;
25
+ html: string;
26
+ from?: string;
27
+ replyTo?: string;
28
+ tags?: Array<{ name: string; value: string }>;
29
+ headers?: Record<string, string>;
30
+ }) => {
31
+ const { data, error } = await resend.emails.send({
32
+ from:
33
+ input.from ??
34
+ process.env.RESEND_FROM_EMAIL ??
35
+ "Hogsend <noreply@hogsend.com>",
36
+ to: input.to,
37
+ subject: input.subject,
38
+ html: input.html,
39
+ replyTo: input.replyTo,
40
+ tags: input.tags,
41
+ headers: input.headers,
42
+ });
43
+
44
+ if (error) {
45
+ const name = (error as { name?: string }).name ?? "";
46
+ if (NON_RETRYABLE_CODES.has(name)) {
47
+ throw new NonRetryableError(`${name}: ${error.message}`);
48
+ }
49
+ throw new Error(`Failed to send email: ${error.message}`);
50
+ }
51
+
52
+ return { emailId: data?.id ?? "" };
53
+ },
54
+ });