@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.
- package/LICENSE +93 -0
- package/README.md +18 -0
- package/package.json +58 -0
- package/src/app.ts +102 -0
- package/src/container.ts +172 -0
- package/src/env.ts +56 -0
- package/src/index.ts +114 -0
- package/src/journeys/define-journey.ts +188 -0
- package/src/journeys/journey-context.ts +179 -0
- package/src/journeys/registry-singleton.ts +21 -0
- package/src/journeys/registry.ts +53 -0
- package/src/lib/alerting.ts +205 -0
- package/src/lib/api-key-hash.ts +19 -0
- package/src/lib/auth.ts +39 -0
- package/src/lib/backfill.ts +84 -0
- package/src/lib/contacts.ts +68 -0
- package/src/lib/db.ts +13 -0
- package/src/lib/email-service-types.ts +115 -0
- package/src/lib/email-stats.ts +33 -0
- package/src/lib/email.ts +94 -0
- package/src/lib/enrollment-guards.ts +56 -0
- package/src/lib/hatchet.ts +20 -0
- package/src/lib/html.ts +25 -0
- package/src/lib/ingestion.ts +162 -0
- package/src/lib/logger.ts +32 -0
- package/src/lib/mailer.ts +266 -0
- package/src/lib/notifications.ts +61 -0
- package/src/lib/posthog.ts +19 -0
- package/src/lib/redis.ts +30 -0
- package/src/lib/schemas.ts +8 -0
- package/src/lib/tracked.ts +175 -0
- package/src/lib/tracking-event-names.ts +5 -0
- package/src/lib/tracking-events.ts +84 -0
- package/src/lib/tracking.ts +78 -0
- package/src/middleware/api-key.ts +129 -0
- package/src/middleware/audit.ts +47 -0
- package/src/middleware/auth.ts +24 -0
- package/src/middleware/error-handler.ts +22 -0
- package/src/middleware/rate-limit.ts +65 -0
- package/src/middleware/request-logger.ts +19 -0
- package/src/routes/admin/alerts.ts +347 -0
- package/src/routes/admin/api-keys.ts +211 -0
- package/src/routes/admin/audit-logs.ts +102 -0
- package/src/routes/admin/bulk.ts +503 -0
- package/src/routes/admin/contacts.ts +342 -0
- package/src/routes/admin/dlq.ts +202 -0
- package/src/routes/admin/emails.ts +269 -0
- package/src/routes/admin/events.ts +132 -0
- package/src/routes/admin/index.ts +36 -0
- package/src/routes/admin/journey-logs.ts +117 -0
- package/src/routes/admin/journeys.ts +677 -0
- package/src/routes/admin/metrics.ts +559 -0
- package/src/routes/admin/preferences.ts +165 -0
- package/src/routes/admin/timeline.ts +221 -0
- package/src/routes/email/index.ts +8 -0
- package/src/routes/email/preferences.ts +144 -0
- package/src/routes/email/unsubscribe.ts +161 -0
- package/src/routes/health.ts +131 -0
- package/src/routes/index.ts +32 -0
- package/src/routes/ingest.ts +71 -0
- package/src/routes/tracking/click.ts +103 -0
- package/src/routes/tracking/index.ts +9 -0
- package/src/routes/tracking/open.ts +71 -0
- package/src/routes/webhooks/index.ts +17 -0
- package/src/routes/webhooks/resend.ts +68 -0
- package/src/routes/webhooks/sources.ts +97 -0
- package/src/webhook-sources/define-webhook-source.ts +34 -0
- package/src/worker.ts +64 -0
- package/src/workflows/check-alerts.ts +24 -0
- package/src/workflows/import-contacts.ts +134 -0
- 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
|
+
});
|