@soulbatical/tetra-core 0.10.4 → 0.11.0
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 +78 -38
- package/dist/core/createApp.d.ts +1 -1
- package/dist/core/createApp.d.ts.map +1 -1
- package/dist/core/createApp.js +77 -2
- package/dist/core/createApp.js.map +1 -1
- package/dist/core/dualWriteProxy.d.ts +7 -2
- package/dist/core/dualWriteProxy.d.ts.map +1 -1
- package/dist/core/dualWriteProxy.js +16 -5
- package/dist/core/dualWriteProxy.js.map +1 -1
- package/dist/core/routeContext.d.ts +24 -0
- package/dist/core/routeContext.d.ts.map +1 -1
- package/dist/core/routeContext.js +31 -4
- package/dist/core/routeContext.js.map +1 -1
- package/dist/core/systemDb.d.ts +2 -2
- package/dist/core/systemDb.js +2 -2
- package/dist/generators/rls-checker.d.ts +1 -1
- package/dist/generators/rls-checker.js +1 -1
- package/dist/generators/rls-exec-sql.d.ts +1 -1
- package/dist/generators/rls-exec-sql.js +1 -1
- package/dist/generators/rpc/index.d.ts +1 -1
- package/dist/generators/rpc/index.js +1 -1
- package/dist/index.d.ts +3 -31
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -32
- package/dist/index.js.map +1 -1
- package/dist/middleware/securityMiddleware.d.ts +1 -1
- package/dist/middleware/securityMiddleware.d.ts.map +1 -1
- package/dist/middleware/validateBody.d.ts.map +1 -1
- package/dist/middleware/validateBody.js +51 -8
- package/dist/middleware/validateBody.js.map +1 -1
- package/dist/shared/rfc7807ErrorResponse.d.ts +7 -0
- package/dist/shared/rfc7807ErrorResponse.d.ts.map +1 -1
- package/dist/shared/rfc7807ErrorResponse.js +19 -5
- package/dist/shared/rfc7807ErrorResponse.js.map +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +16 -1
- package/dist/utils/logger.js.map +1 -1
- package/package.json +33 -77
- package/dist/affiliate.d.ts +0 -11
- package/dist/affiliate.d.ts.map +0 -1
- package/dist/affiliate.js +0 -10
- package/dist/affiliate.js.map +0 -1
- package/dist/billing.d.ts +0 -8
- package/dist/billing.d.ts.map +0 -1
- package/dist/billing.js +0 -7
- package/dist/billing.js.map +0 -1
- package/dist/email.d.ts +0 -9
- package/dist/email.d.ts.map +0 -1
- package/dist/email.js +0 -8
- package/dist/email.js.map +0 -1
- package/dist/generators/rls-exec-sql.sql +0 -57
- package/dist/generators.d.ts +0 -15
- package/dist/generators.d.ts.map +0 -1
- package/dist/generators.js +0 -12
- package/dist/generators.js.map +0 -1
- package/dist/mcp.d.ts +0 -8
- package/dist/mcp.d.ts.map +0 -1
- package/dist/mcp.js +0 -7
- package/dist/mcp.js.map +0 -1
- package/dist/planner.d.ts +0 -8
- package/dist/planner.d.ts.map +0 -1
- package/dist/planner.js +0 -7
- package/dist/planner.js.map +0 -1
- package/dist/shared/affiliate/AffiliateAttributionService.d.ts +0 -47
- package/dist/shared/affiliate/AffiliateAttributionService.d.ts.map +0 -1
- package/dist/shared/affiliate/AffiliateAttributionService.js +0 -308
- package/dist/shared/affiliate/AffiliateAttributionService.js.map +0 -1
- package/dist/shared/affiliate/AffiliateClickService.d.ts +0 -35
- package/dist/shared/affiliate/AffiliateClickService.d.ts.map +0 -1
- package/dist/shared/affiliate/AffiliateClickService.js +0 -87
- package/dist/shared/affiliate/AffiliateClickService.js.map +0 -1
- package/dist/shared/affiliate/affiliateFeatureConfig.d.ts +0 -11
- package/dist/shared/affiliate/affiliateFeatureConfig.d.ts.map +0 -1
- package/dist/shared/affiliate/affiliateFeatureConfig.js +0 -242
- package/dist/shared/affiliate/affiliateFeatureConfig.js.map +0 -1
- package/dist/shared/affiliate/index.d.ts +0 -11
- package/dist/shared/affiliate/index.d.ts.map +0 -1
- package/dist/shared/affiliate/index.js +0 -13
- package/dist/shared/affiliate/index.js.map +0 -1
- package/dist/shared/affiliate/routes.d.ts +0 -87
- package/dist/shared/affiliate/routes.d.ts.map +0 -1
- package/dist/shared/affiliate/routes.js +0 -404
- package/dist/shared/affiliate/routes.js.map +0 -1
- package/dist/shared/affiliate/types.d.ts +0 -170
- package/dist/shared/affiliate/types.d.ts.map +0 -1
- package/dist/shared/affiliate/types.js +0 -11
- package/dist/shared/affiliate/types.js.map +0 -1
- package/dist/shared/billing/BillingService.d.ts +0 -56
- package/dist/shared/billing/BillingService.d.ts.map +0 -1
- package/dist/shared/billing/BillingService.js +0 -588
- package/dist/shared/billing/BillingService.js.map +0 -1
- package/dist/shared/billing/SeatBillingService.d.ts +0 -106
- package/dist/shared/billing/SeatBillingService.d.ts.map +0 -1
- package/dist/shared/billing/SeatBillingService.js +0 -292
- package/dist/shared/billing/SeatBillingService.js.map +0 -1
- package/dist/shared/billing/index.d.ts +0 -30
- package/dist/shared/billing/index.d.ts.map +0 -1
- package/dist/shared/billing/index.js +0 -27
- package/dist/shared/billing/index.js.map +0 -1
- package/dist/shared/billing/routes.d.ts +0 -45
- package/dist/shared/billing/routes.d.ts.map +0 -1
- package/dist/shared/billing/routes.js +0 -184
- package/dist/shared/billing/routes.js.map +0 -1
- package/dist/shared/billing/seat-pricing.d.ts +0 -53
- package/dist/shared/billing/seat-pricing.d.ts.map +0 -1
- package/dist/shared/billing/seat-pricing.js +0 -81
- package/dist/shared/billing/seat-pricing.js.map +0 -1
- package/dist/shared/billing/types.d.ts +0 -109
- package/dist/shared/billing/types.d.ts.map +0 -1
- package/dist/shared/billing/types.js +0 -8
- package/dist/shared/billing/types.js.map +0 -1
- package/dist/shared/email/EmailService.d.ts +0 -64
- package/dist/shared/email/EmailService.d.ts.map +0 -1
- package/dist/shared/email/EmailService.js +0 -300
- package/dist/shared/email/EmailService.js.map +0 -1
- package/dist/shared/email/adminRoutes.d.ts +0 -30
- package/dist/shared/email/adminRoutes.d.ts.map +0 -1
- package/dist/shared/email/adminRoutes.js +0 -227
- package/dist/shared/email/adminRoutes.js.map +0 -1
- package/dist/shared/email/gmail.d.ts +0 -208
- package/dist/shared/email/gmail.d.ts.map +0 -1
- package/dist/shared/email/gmail.js +0 -626
- package/dist/shared/email/gmail.js.map +0 -1
- package/dist/shared/email/index.d.ts +0 -15
- package/dist/shared/email/index.d.ts.map +0 -1
- package/dist/shared/email/index.js +0 -18
- package/dist/shared/email/index.js.map +0 -1
- package/dist/shared/email/mailgun.d.ts +0 -18
- package/dist/shared/email/mailgun.d.ts.map +0 -1
- package/dist/shared/email/mailgun.js +0 -76
- package/dist/shared/email/mailgun.js.map +0 -1
- package/dist/shared/email/sanitize.d.ts +0 -25
- package/dist/shared/email/sanitize.d.ts.map +0 -1
- package/dist/shared/email/sanitize.js +0 -39
- package/dist/shared/email/sanitize.js.map +0 -1
- package/dist/shared/email/smtp.d.ts +0 -20
- package/dist/shared/email/smtp.d.ts.map +0 -1
- package/dist/shared/email/smtp.js +0 -53
- package/dist/shared/email/smtp.js.map +0 -1
- package/dist/shared/email/types.d.ts +0 -113
- package/dist/shared/email/types.d.ts.map +0 -1
- package/dist/shared/email/types.js +0 -7
- package/dist/shared/email/types.js.map +0 -1
- package/dist/shared/email/webhookRoutes.d.ts +0 -29
- package/dist/shared/email/webhookRoutes.d.ts.map +0 -1
- package/dist/shared/email/webhookRoutes.js +0 -125
- package/dist/shared/email/webhookRoutes.js.map +0 -1
- package/dist/shared/mcp/index.d.ts +0 -51
- package/dist/shared/mcp/index.d.ts.map +0 -1
- package/dist/shared/mcp/index.js +0 -51
- package/dist/shared/mcp/index.js.map +0 -1
- package/dist/shared/mcp/mcp-auth-routes.d.ts +0 -26
- package/dist/shared/mcp/mcp-auth-routes.d.ts.map +0 -1
- package/dist/shared/mcp/mcp-auth-routes.js +0 -141
- package/dist/shared/mcp/mcp-auth-routes.js.map +0 -1
- package/dist/shared/mcp/mcp-db.d.ts +0 -99
- package/dist/shared/mcp/mcp-db.d.ts.map +0 -1
- package/dist/shared/mcp/mcp-db.js +0 -106
- package/dist/shared/mcp/mcp-db.js.map +0 -1
- package/dist/shared/mcp/mcp-routes.d.ts +0 -29
- package/dist/shared/mcp/mcp-routes.d.ts.map +0 -1
- package/dist/shared/mcp/mcp-routes.js +0 -171
- package/dist/shared/mcp/mcp-routes.js.map +0 -1
- package/dist/shared/mcp/mcp-tokens-routes.d.ts +0 -35
- package/dist/shared/mcp/mcp-tokens-routes.d.ts.map +0 -1
- package/dist/shared/mcp/mcp-tokens-routes.js +0 -94
- package/dist/shared/mcp/mcp-tokens-routes.js.map +0 -1
- package/dist/shared/mcp/mcp-usage-routes.d.ts +0 -17
- package/dist/shared/mcp/mcp-usage-routes.d.ts.map +0 -1
- package/dist/shared/mcp/mcp-usage-routes.js +0 -81
- package/dist/shared/mcp/mcp-usage-routes.js.map +0 -1
- package/dist/shared/mcp/tenant-context.d.ts +0 -59
- package/dist/shared/mcp/tenant-context.d.ts.map +0 -1
- package/dist/shared/mcp/tenant-context.js +0 -136
- package/dist/shared/mcp/tenant-context.js.map +0 -1
- package/dist/shared/mcp/types.d.ts +0 -74
- package/dist/shared/mcp/types.d.ts.map +0 -1
- package/dist/shared/mcp/types.js +0 -7
- package/dist/shared/mcp/types.js.map +0 -1
- package/dist/shared/planner/GoogleCalendarService.d.ts +0 -137
- package/dist/shared/planner/GoogleCalendarService.d.ts.map +0 -1
- package/dist/shared/planner/GoogleCalendarService.js +0 -525
- package/dist/shared/planner/GoogleCalendarService.js.map +0 -1
- package/dist/shared/planner/PlannerService.d.ts +0 -264
- package/dist/shared/planner/PlannerService.d.ts.map +0 -1
- package/dist/shared/planner/PlannerService.js +0 -1393
- package/dist/shared/planner/PlannerService.js.map +0 -1
- package/dist/shared/planner/index.d.ts +0 -37
- package/dist/shared/planner/index.d.ts.map +0 -1
- package/dist/shared/planner/index.js +0 -35
- package/dist/shared/planner/index.js.map +0 -1
- package/dist/shared/planner/intervals.d.ts +0 -60
- package/dist/shared/planner/intervals.d.ts.map +0 -1
- package/dist/shared/planner/intervals.js +0 -141
- package/dist/shared/planner/intervals.js.map +0 -1
- package/dist/shared/planner/routes.d.ts +0 -69
- package/dist/shared/planner/routes.d.ts.map +0 -1
- package/dist/shared/planner/routes.js +0 -770
- package/dist/shared/planner/routes.js.map +0 -1
- package/dist/shared/planner/types.d.ts +0 -328
- package/dist/shared/planner/types.d.ts.map +0 -1
- package/dist/shared/planner/types.js +0 -9
- package/dist/shared/planner/types.js.map +0 -1
- package/dist/shared/storage/ImageProcessingService.d.ts +0 -32
- package/dist/shared/storage/ImageProcessingService.d.ts.map +0 -1
- package/dist/shared/storage/ImageProcessingService.js +0 -127
- package/dist/shared/storage/ImageProcessingService.js.map +0 -1
- package/dist/shared/storage/StorageProxyService.d.ts +0 -47
- package/dist/shared/storage/StorageProxyService.d.ts.map +0 -1
- package/dist/shared/storage/StorageProxyService.js +0 -196
- package/dist/shared/storage/StorageProxyService.js.map +0 -1
- package/dist/shared/storage/StorageUploadService.d.ts +0 -126
- package/dist/shared/storage/StorageUploadService.d.ts.map +0 -1
- package/dist/shared/storage/StorageUploadService.js +0 -206
- package/dist/shared/storage/StorageUploadService.js.map +0 -1
- package/dist/shared/storage/creative-urls.d.ts +0 -14
- package/dist/shared/storage/creative-urls.d.ts.map +0 -1
- package/dist/shared/storage/creative-urls.js +0 -30
- package/dist/shared/storage/creative-urls.js.map +0 -1
- package/dist/shared/storage/index.d.ts +0 -28
- package/dist/shared/storage/index.d.ts.map +0 -1
- package/dist/shared/storage/index.js +0 -27
- package/dist/shared/storage/index.js.map +0 -1
- package/dist/shared/storage/routes.d.ts +0 -42
- package/dist/shared/storage/routes.d.ts.map +0 -1
- package/dist/shared/storage/routes.js +0 -160
- package/dist/shared/storage/routes.js.map +0 -1
- package/dist/shared/storage/types.d.ts +0 -53
- package/dist/shared/storage/types.d.ts.map +0 -1
- package/dist/shared/storage/types.js +0 -2
- package/dist/shared/storage/types.js.map +0 -1
- package/dist/shared/telegram/index.d.ts +0 -4
- package/dist/shared/telegram/index.d.ts.map +0 -1
- package/dist/shared/telegram/index.js +0 -3
- package/dist/shared/telegram/index.js.map +0 -1
- package/dist/shared/telegram/routes.d.ts +0 -43
- package/dist/shared/telegram/routes.d.ts.map +0 -1
- package/dist/shared/telegram/routes.js +0 -868
- package/dist/shared/telegram/routes.js.map +0 -1
- package/dist/shared/telegram/types.d.ts +0 -168
- package/dist/shared/telegram/types.d.ts.map +0 -1
- package/dist/shared/telegram/types.js +0 -7
- package/dist/shared/telegram/types.js.map +0 -1
- package/dist/shared/telegram/utils.d.ts +0 -44
- package/dist/shared/telegram/utils.d.ts.map +0 -1
- package/dist/shared/telegram/utils.js +0 -121
- package/dist/shared/telegram/utils.js.map +0 -1
- package/dist/storage.d.ts +0 -9
- package/dist/storage.d.ts.map +0 -1
- package/dist/storage.js +0 -8
- package/dist/storage.js.map +0 -1
- package/dist/telemetry.d.ts +0 -9
- package/dist/telemetry.d.ts.map +0 -1
- package/dist/telemetry.js +0 -8
- package/dist/telemetry.js.map +0 -1
- package/scripts/postinstall.js +0 -79
- package/src/shared/affiliate/migrations/001_create_affiliates.sql +0 -49
- package/src/shared/affiliate/migrations/002_create_affiliate_commissions.sql +0 -31
- package/src/shared/affiliate/migrations/003_create_affiliate_clicks.sql +0 -26
- package/src/shared/affiliate/migrations/004_create_affiliate_payments.sql +0 -34
- package/src/shared/affiliate/migrations/005_create_affiliate_tier_history.sql +0 -19
- package/src/shared/affiliate/migrations/006_create_affiliate_rpc_functions.sql +0 -209
- package/src/shared/affiliate/migrations/007_create_affiliate_rls_policies.sql +0 -123
- package/src/shared/billing/migrations/00000000000001_billing.sql +0 -114
- package/src/shared/email/migrations/000_create_email_logs.sql +0 -27
- package/src/shared/email/migrations/001_create_email_templates.sql +0 -27
- package/src/shared/email/migrations/002_add_rls_baseline_policies.sql +0 -37
- package/src/shared/email/migrations/003_create_gmail_accounts.sql +0 -82
- package/src/shared/email/migrations/004_add_email_logs_tracking_columns.sql +0 -15
- package/src/shared/mcp/migrations/001_mcp_api_tokens.sql +0 -21
- package/src/shared/mcp/migrations/002_mcp_audit_log.sql +0 -16
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/email/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAG7D,OAAO,EACL,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,eAAe,EACf,wBAAwB,EACxB,yBAAyB,EACzB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAGtF,YAAY,EACV,eAAe,EACf,WAAW,EACX,aAAa,EACb,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Email Module — Barrel Export
|
|
3
|
-
*
|
|
4
|
-
* @module @soulbatical/tetra-core/email
|
|
5
|
-
*/
|
|
6
|
-
// Service
|
|
7
|
-
export { EmailService } from './EmailService.js';
|
|
8
|
-
// Transport helpers
|
|
9
|
-
export { sendMailgunEmail } from './mailgun.js';
|
|
10
|
-
export { sendSmtpEmail } from './smtp.js';
|
|
11
|
-
// Route factories
|
|
12
|
-
export { addEmailAdminRoutes } from './adminRoutes.js';
|
|
13
|
-
export { addMailgunWebhookRoutes } from './webhookRoutes.js';
|
|
14
|
-
// Gmail (OAuth2 API transport + client for read/search/attachments)
|
|
15
|
-
export { GmailClient, getGmailClient, listGmailAccounts, clearGmailClientCache, disconnectGmail, getGmailAuthUrl, startGmailOAuth, getGmailAuthServerStatus, resetGmailAuthServerState, exchangeGmailCode, addGmailOAuthRoutes, } from './gmail.js';
|
|
16
|
-
// Sanitization
|
|
17
|
-
export { escapeHtml, stripCRLF, sanitizeEmailHeader, stripHtml } from './sanitize.js';
|
|
18
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/shared/email/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,UAAU;AACV,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,oBAAoB;AACpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,kBAAkB;AAClB,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,oEAAoE;AACpE,OAAO,EACL,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,eAAe,EACf,wBAAwB,EACxB,yBAAyB,EACzB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAiBpB,eAAe;AACf,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mailgun email helper — native fetch, no axios.
|
|
3
|
-
* Graceful no-op when credentials are missing.
|
|
4
|
-
*/
|
|
5
|
-
import type { MailgunResponse, EmailAttachment } from './types.js';
|
|
6
|
-
export declare function sendMailgunEmail(params: {
|
|
7
|
-
from: string;
|
|
8
|
-
to: string;
|
|
9
|
-
subject: string;
|
|
10
|
-
html: string;
|
|
11
|
-
text?: string;
|
|
12
|
-
replyTo?: string;
|
|
13
|
-
attachments?: EmailAttachment[];
|
|
14
|
-
apiKey?: string;
|
|
15
|
-
domain?: string;
|
|
16
|
-
endpoint?: string;
|
|
17
|
-
}): Promise<MailgunResponse>;
|
|
18
|
-
//# sourceMappingURL=mailgun.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mailgun.d.ts","sourceRoot":"","sources":["../../../src/shared/email/mailgun.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAInE,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,eAAe,CAAC,CAyE3B"}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mailgun email helper — native fetch, no axios.
|
|
3
|
-
* Graceful no-op when credentials are missing.
|
|
4
|
-
*/
|
|
5
|
-
const DEFAULT_EU_ENDPOINT = 'https://api.eu.mailgun.net/v3';
|
|
6
|
-
export async function sendMailgunEmail(params) {
|
|
7
|
-
const { apiKey, domain } = params;
|
|
8
|
-
if (!apiKey || !domain) {
|
|
9
|
-
console.warn('[email/mailgun] credentials missing — email not sent');
|
|
10
|
-
return { success: false, message: 'Mailgun not configured' };
|
|
11
|
-
}
|
|
12
|
-
const baseUrl = params.endpoint || DEFAULT_EU_ENDPOINT;
|
|
13
|
-
try {
|
|
14
|
-
let body;
|
|
15
|
-
let contentType;
|
|
16
|
-
if (params.attachments?.length) {
|
|
17
|
-
// Use FormData for multipart (attachments)
|
|
18
|
-
const formData = new FormData();
|
|
19
|
-
formData.append('from', params.from);
|
|
20
|
-
formData.append('to', params.to);
|
|
21
|
-
formData.append('subject', params.subject);
|
|
22
|
-
formData.append('html', params.html);
|
|
23
|
-
if (params.text)
|
|
24
|
-
formData.append('text', params.text);
|
|
25
|
-
if (params.replyTo)
|
|
26
|
-
formData.append('h:Reply-To', params.replyTo);
|
|
27
|
-
for (const att of params.attachments) {
|
|
28
|
-
const blob = new Blob([att.data], { type: att.contentType || 'application/octet-stream' });
|
|
29
|
-
formData.append('attachment', blob, att.filename);
|
|
30
|
-
}
|
|
31
|
-
body = formData;
|
|
32
|
-
// Let fetch set the Content-Type with boundary
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
// Simple URL-encoded form (no attachments)
|
|
36
|
-
const formData = new URLSearchParams();
|
|
37
|
-
formData.append('from', params.from);
|
|
38
|
-
formData.append('to', params.to);
|
|
39
|
-
formData.append('subject', params.subject);
|
|
40
|
-
formData.append('html', params.html);
|
|
41
|
-
if (params.text)
|
|
42
|
-
formData.append('text', params.text);
|
|
43
|
-
if (params.replyTo)
|
|
44
|
-
formData.append('h:Reply-To', params.replyTo);
|
|
45
|
-
body = formData.toString();
|
|
46
|
-
contentType = 'application/x-www-form-urlencoded';
|
|
47
|
-
}
|
|
48
|
-
const headers = {
|
|
49
|
-
Authorization: 'Basic ' + Buffer.from(`api:${apiKey}`).toString('base64'),
|
|
50
|
-
};
|
|
51
|
-
if (contentType)
|
|
52
|
-
headers['Content-Type'] = contentType;
|
|
53
|
-
const resp = await fetch(`${baseUrl}/${domain}/messages`, {
|
|
54
|
-
method: 'POST',
|
|
55
|
-
headers,
|
|
56
|
-
body,
|
|
57
|
-
});
|
|
58
|
-
if (!resp.ok) {
|
|
59
|
-
const text = (await resp.text()).slice(0, 500);
|
|
60
|
-
console.error(`[email/mailgun] API error ${resp.status}: ${text}`);
|
|
61
|
-
return { success: false, message: `Mailgun error: ${resp.status}` };
|
|
62
|
-
}
|
|
63
|
-
const data = (await resp.json());
|
|
64
|
-
return {
|
|
65
|
-
success: true,
|
|
66
|
-
message: data.message || 'Email sent',
|
|
67
|
-
messageId: data.id,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
catch (err) {
|
|
71
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
72
|
-
console.error('[email/mailgun] send failed:', msg);
|
|
73
|
-
return { success: false, message: `Send failed: ${msg}` };
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
//# sourceMappingURL=mailgun.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mailgun.js","sourceRoot":"","sources":["../../../src/shared/email/mailgun.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HTML sanitization helpers for email content.
|
|
3
|
-
*
|
|
4
|
-
* @module @soulbatical/tetra-core/email/sanitize
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* Escape HTML special characters to prevent XSS in email templates.
|
|
8
|
-
* Handles all OWASP-recommended characters: & < > " '
|
|
9
|
-
*/
|
|
10
|
-
export declare function escapeHtml(str: string, maxLen?: number): string;
|
|
11
|
-
/**
|
|
12
|
-
* Strip CRLF characters to prevent SMTP header injection.
|
|
13
|
-
* Use on ALL email header fields: to, from, subject, cc, bcc, reply-to.
|
|
14
|
-
*/
|
|
15
|
-
export declare function stripCRLF(str: string): string;
|
|
16
|
-
/**
|
|
17
|
-
* Sanitize an email header field: strip CRLF + trim + length limit.
|
|
18
|
-
* Combines SMTP injection prevention with basic hygiene.
|
|
19
|
-
*/
|
|
20
|
-
export declare function sanitizeEmailHeader(str: string, maxLen?: number): string;
|
|
21
|
-
/**
|
|
22
|
-
* Strip all HTML tags from a string. Use for user input that should be plain text.
|
|
23
|
-
*/
|
|
24
|
-
export declare function stripHtml(str: string): string;
|
|
25
|
-
//# sourceMappingURL=sanitize.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../../src/shared/email/sanitize.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,SAAM,GAAG,MAAM,CAQ5D;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,SAAM,GAAG,MAAM,CAErE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C"}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HTML sanitization helpers for email content.
|
|
3
|
-
*
|
|
4
|
-
* @module @soulbatical/tetra-core/email/sanitize
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* Escape HTML special characters to prevent XSS in email templates.
|
|
8
|
-
* Handles all OWASP-recommended characters: & < > " '
|
|
9
|
-
*/
|
|
10
|
-
export function escapeHtml(str, maxLen = 500) {
|
|
11
|
-
return str
|
|
12
|
-
.slice(0, maxLen)
|
|
13
|
-
.replace(/&/g, '&')
|
|
14
|
-
.replace(/</g, '<')
|
|
15
|
-
.replace(/>/g, '>')
|
|
16
|
-
.replace(/"/g, '"')
|
|
17
|
-
.replace(/'/g, ''');
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Strip CRLF characters to prevent SMTP header injection.
|
|
21
|
-
* Use on ALL email header fields: to, from, subject, cc, bcc, reply-to.
|
|
22
|
-
*/
|
|
23
|
-
export function stripCRLF(str) {
|
|
24
|
-
return str.replace(/[\r\n]/g, '');
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Sanitize an email header field: strip CRLF + trim + length limit.
|
|
28
|
-
* Combines SMTP injection prevention with basic hygiene.
|
|
29
|
-
*/
|
|
30
|
-
export function sanitizeEmailHeader(str, maxLen = 200) {
|
|
31
|
-
return stripCRLF(str).trim().slice(0, maxLen);
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Strip all HTML tags from a string. Use for user input that should be plain text.
|
|
35
|
-
*/
|
|
36
|
-
export function stripHtml(str) {
|
|
37
|
-
return str.replace(/<[^>]*>/g, '');
|
|
38
|
-
}
|
|
39
|
-
//# sourceMappingURL=sanitize.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../../src/shared/email/sanitize.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,MAAM,GAAG,GAAG;IAClD,OAAO,GAAG;SACP,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC;SAChB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,OAAO,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;AACpC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAW,EAAE,MAAM,GAAG,GAAG;IAC3D,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,OAAO,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AACrC,CAAC"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SMTP email helper — uses nodemailer for sending via SMTP (Gmail, Outlook, etc.).
|
|
3
|
-
* Graceful no-op when credentials are missing.
|
|
4
|
-
*/
|
|
5
|
-
import type { SmtpResponse, EmailAttachment } from './types.js';
|
|
6
|
-
export declare function sendSmtpEmail(params: {
|
|
7
|
-
from: string;
|
|
8
|
-
to: string;
|
|
9
|
-
subject: string;
|
|
10
|
-
html: string;
|
|
11
|
-
text?: string;
|
|
12
|
-
replyTo?: string;
|
|
13
|
-
attachments?: EmailAttachment[];
|
|
14
|
-
smtpHost: string;
|
|
15
|
-
smtpPort: number;
|
|
16
|
-
smtpUser: string;
|
|
17
|
-
smtpPass: string;
|
|
18
|
-
smtpSecure?: boolean;
|
|
19
|
-
}): Promise<SmtpResponse>;
|
|
20
|
-
//# sourceMappingURL=smtp.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"smtp.d.ts","sourceRoot":"","sources":["../../../src/shared/email/smtp.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEhE,wBAAsB,aAAa,CAAC,MAAM,EAAE;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GAAG,OAAO,CAAC,YAAY,CAAC,CAoDxB"}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SMTP email helper — uses nodemailer for sending via SMTP (Gmail, Outlook, etc.).
|
|
3
|
-
* Graceful no-op when credentials are missing.
|
|
4
|
-
*/
|
|
5
|
-
export async function sendSmtpEmail(params) {
|
|
6
|
-
const { smtpHost, smtpUser, smtpPass } = params;
|
|
7
|
-
if (!smtpHost || !smtpUser || !smtpPass) {
|
|
8
|
-
console.warn('[email/smtp] credentials missing — email not sent');
|
|
9
|
-
return { success: false, message: 'SMTP not configured' };
|
|
10
|
-
}
|
|
11
|
-
try {
|
|
12
|
-
// Dynamic import to keep nodemailer optional at runtime
|
|
13
|
-
const nodemailer = await import('nodemailer');
|
|
14
|
-
const transporter = nodemailer.default.createTransport({
|
|
15
|
-
host: params.smtpHost,
|
|
16
|
-
port: params.smtpPort,
|
|
17
|
-
secure: params.smtpSecure ?? params.smtpPort === 465,
|
|
18
|
-
auth: {
|
|
19
|
-
user: params.smtpUser,
|
|
20
|
-
pass: params.smtpPass,
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
const mailOpts = {
|
|
24
|
-
from: params.from,
|
|
25
|
-
to: params.to,
|
|
26
|
-
subject: params.subject,
|
|
27
|
-
html: params.html,
|
|
28
|
-
};
|
|
29
|
-
if (params.text)
|
|
30
|
-
mailOpts.text = params.text;
|
|
31
|
-
if (params.replyTo)
|
|
32
|
-
mailOpts.replyTo = params.replyTo;
|
|
33
|
-
if (params.attachments?.length) {
|
|
34
|
-
mailOpts.attachments = params.attachments.map(att => ({
|
|
35
|
-
filename: att.filename,
|
|
36
|
-
content: att.data,
|
|
37
|
-
contentType: att.contentType || 'application/octet-stream',
|
|
38
|
-
}));
|
|
39
|
-
}
|
|
40
|
-
const info = await transporter.sendMail(mailOpts);
|
|
41
|
-
return {
|
|
42
|
-
success: true,
|
|
43
|
-
message: 'Email sent via SMTP',
|
|
44
|
-
messageId: info.messageId,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
catch (err) {
|
|
48
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
49
|
-
console.error('[email/smtp] send failed:', msg);
|
|
50
|
-
return { success: false, message: `SMTP send failed: ${msg}` };
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
//# sourceMappingURL=smtp.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"smtp.js","sourceRoot":"","sources":["../../../src/shared/email/smtp.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAanC;IACC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC;IAEhD,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;QAClE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC;IAC5D,CAAC;IAED,IAAI,CAAC;QACH,wDAAwD;QACxD,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAE9C,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,eAAe,CAAC;YACrD,IAAI,EAAE,MAAM,CAAC,QAAQ;YACrB,IAAI,EAAE,MAAM,CAAC,QAAQ;YACrB,MAAM,EAAE,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,QAAQ,KAAK,GAAG;YACpD,IAAI,EAAE;gBACJ,IAAI,EAAE,MAAM,CAAC,QAAQ;gBACrB,IAAI,EAAE,MAAM,CAAC,QAAQ;aACtB;SACF,CAAC,CAAC;QAEH,MAAM,QAAQ,GAA4B;YACxC,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,IAAI,EAAE,MAAM,CAAC,IAAI;SAClB,CAAC;QAEF,IAAI,MAAM,CAAC,IAAI;YAAE,QAAQ,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QAC7C,IAAI,MAAM,CAAC,OAAO;YAAE,QAAQ,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAEtD,IAAI,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;YAC/B,QAAQ,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACpD,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,OAAO,EAAE,GAAG,CAAC,IAAI;gBACjB,WAAW,EAAE,GAAG,CAAC,WAAW,IAAI,0BAA0B;aAC3D,CAAC,CAAC,CAAC;QACN,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAElD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,qBAAqB;YAC9B,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAC;QAChD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,qBAAqB,GAAG,EAAE,EAAE,CAAC;IACjE,CAAC;AACH,CAAC"}
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Email Module — Type definitions
|
|
3
|
-
*
|
|
4
|
-
* @module @soulbatical/tetra-core/email
|
|
5
|
-
*/
|
|
6
|
-
export interface EmailAttachment {
|
|
7
|
-
filename: string;
|
|
8
|
-
data: Buffer;
|
|
9
|
-
contentType?: string;
|
|
10
|
-
}
|
|
11
|
-
export interface EmailConfig {
|
|
12
|
-
/** From address, e.g. "VinciFox <noreply@vincifox.com>" */
|
|
13
|
-
fromAddress: string;
|
|
14
|
-
/** Default language for template lookup fallback */
|
|
15
|
-
defaultLanguage: 'nl' | 'en';
|
|
16
|
-
/** Frontend URL for unsubscribe links etc. */
|
|
17
|
-
frontendUrl: string;
|
|
18
|
-
/** Transport: 'gmail', 'smtp', or 'mailgun' (default: auto-detect — gmail > smtp > mailgun) */
|
|
19
|
-
transport?: 'gmail' | 'smtp' | 'mailgun';
|
|
20
|
-
/** Mailgun API key — no-op when missing */
|
|
21
|
-
mailgunApiKey?: string;
|
|
22
|
-
/** Mailgun domain, e.g. mg.vincifox.com */
|
|
23
|
-
mailgunDomain?: string;
|
|
24
|
-
/** Mailgun API endpoint — defaults to EU endpoint */
|
|
25
|
-
mailgunEndpoint?: string;
|
|
26
|
-
/** Mailgun webhook signing key — required for webhook signature verification */
|
|
27
|
-
mailgunWebhookSigningKey?: string;
|
|
28
|
-
/** SMTP host, e.g. smtp.gmail.com */
|
|
29
|
-
smtpHost?: string;
|
|
30
|
-
/** SMTP port — defaults to 587 */
|
|
31
|
-
smtpPort?: number;
|
|
32
|
-
/** SMTP username (for Gmail: full email address) */
|
|
33
|
-
smtpUser?: string;
|
|
34
|
-
/** SMTP password (for Gmail: App Password, not account password) */
|
|
35
|
-
smtpPass?: string;
|
|
36
|
-
/** Use TLS on connect (port 465). Defaults to false (STARTTLS on 587). */
|
|
37
|
-
smtpSecure?: boolean;
|
|
38
|
-
/** Gmail: user ID (auth.users UUID) whose Gmail account to use for sending */
|
|
39
|
-
gmailUserId?: string;
|
|
40
|
-
/** Gmail: specific email to use (if user has multiple accounts). Optional. */
|
|
41
|
-
gmailEmail?: string;
|
|
42
|
-
}
|
|
43
|
-
export interface SendEmailOpts {
|
|
44
|
-
to: string;
|
|
45
|
-
templateSlug: string;
|
|
46
|
-
variables: Record<string, string>;
|
|
47
|
-
/** Language for template lookup, falls back to config.defaultLanguage */
|
|
48
|
-
language?: string;
|
|
49
|
-
organizationId?: string;
|
|
50
|
-
/** Reply-To address (e.g. for contact forms) */
|
|
51
|
-
replyTo?: string;
|
|
52
|
-
/** File attachments */
|
|
53
|
-
attachments?: EmailAttachment[];
|
|
54
|
-
/** Email type for logging/categorization (e.g. 'transactional', 'contact_admin') */
|
|
55
|
-
emailType?: string;
|
|
56
|
-
/** Arbitrary metadata stored in email_logs for tracking/debugging */
|
|
57
|
-
metadata?: Record<string, unknown>;
|
|
58
|
-
/** Optional FK — consuming project can use this for app-specific references */
|
|
59
|
-
feedbackId?: string;
|
|
60
|
-
/** Subject fallback when DB template is missing */
|
|
61
|
-
fallbackSubject?: string;
|
|
62
|
-
/** HTML fallback when DB template is missing */
|
|
63
|
-
fallbackHtml?: string;
|
|
64
|
-
/** Plain text fallback when DB template is missing */
|
|
65
|
-
fallbackText?: string;
|
|
66
|
-
}
|
|
67
|
-
export interface EmailTemplate {
|
|
68
|
-
id: string;
|
|
69
|
-
slug: string;
|
|
70
|
-
name: string;
|
|
71
|
-
subject: string;
|
|
72
|
-
body_html: string;
|
|
73
|
-
body_text: string | null;
|
|
74
|
-
variables: unknown[];
|
|
75
|
-
language: string;
|
|
76
|
-
category: string;
|
|
77
|
-
is_active: boolean;
|
|
78
|
-
organization_id: string | null;
|
|
79
|
-
created_at: string;
|
|
80
|
-
updated_at: string;
|
|
81
|
-
}
|
|
82
|
-
export interface EmailLogEntry {
|
|
83
|
-
id: string;
|
|
84
|
-
organization_id: string | null;
|
|
85
|
-
template_id: string | null;
|
|
86
|
-
to_email: string;
|
|
87
|
-
subject: string;
|
|
88
|
-
template_slug: string | null;
|
|
89
|
-
variables_used: Record<string, string>;
|
|
90
|
-
email_type: string | null;
|
|
91
|
-
metadata: Record<string, unknown> | null;
|
|
92
|
-
status: 'pending' | 'sent' | 'failed' | 'delivered' | 'opened' | 'clicked' | 'bounced' | 'complained';
|
|
93
|
-
error_message: string | null;
|
|
94
|
-
mailgun_message_id: string | null;
|
|
95
|
-
sent_at: string | null;
|
|
96
|
-
delivered_at: string | null;
|
|
97
|
-
opened_at: string | null;
|
|
98
|
-
clicked_at: string | null;
|
|
99
|
-
created_at: string;
|
|
100
|
-
}
|
|
101
|
-
export interface MailgunResponse {
|
|
102
|
-
success: boolean;
|
|
103
|
-
message: string;
|
|
104
|
-
messageId?: string;
|
|
105
|
-
}
|
|
106
|
-
export interface SmtpResponse {
|
|
107
|
-
success: boolean;
|
|
108
|
-
message: string;
|
|
109
|
-
messageId?: string;
|
|
110
|
-
}
|
|
111
|
-
/** Unified response from any email transport */
|
|
112
|
-
export type EmailSendResponse = MailgunResponse | SmtpResponse;
|
|
113
|
-
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/shared/email/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/shared/email/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mailgun Webhook Routes — optional route factory for delivery tracking.
|
|
3
|
-
*
|
|
4
|
-
* Usage:
|
|
5
|
-
* import { addMailgunWebhookRoutes } from '@soulbatical/tetra-core';
|
|
6
|
-
* addMailgunWebhookRoutes(router, { signingKey: process.env.MAILGUN_WEBHOOK_SIGNING_KEY });
|
|
7
|
-
*
|
|
8
|
-
* @module @soulbatical/tetra-core/email
|
|
9
|
-
*/
|
|
10
|
-
import { Router } from 'express';
|
|
11
|
-
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
12
|
-
interface MailgunWebhookConfig {
|
|
13
|
-
/** Mailgun webhook signing key for signature verification */
|
|
14
|
-
signingKey?: string;
|
|
15
|
-
/** Supabase client (systemDB or service_role) for updating email_logs */
|
|
16
|
-
supabase: SupabaseClient;
|
|
17
|
-
/** Max age of webhook timestamp in seconds (default: 30) */
|
|
18
|
-
maxTimestampAge?: number;
|
|
19
|
-
/** Set true in development to skip signature verification */
|
|
20
|
-
skipVerification?: boolean;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Add Mailgun webhook route to a router.
|
|
24
|
-
* Handles: delivered, opened, clicked, bounced, failed, complained events.
|
|
25
|
-
* Updates email_logs table with delivery tracking data.
|
|
26
|
-
*/
|
|
27
|
-
export declare function addMailgunWebhookRoutes(router: Router, config: MailgunWebhookConfig): void;
|
|
28
|
-
export {};
|
|
29
|
-
//# sourceMappingURL=webhookRoutes.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webhookRoutes.d.ts","sourceRoot":"","sources":["../../../src/shared/email/webhookRoutes.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AAEpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,UAAU,oBAAoB;IAC5B,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,QAAQ,EAAE,cAAc,CAAC;IACzB,4DAA4D;IAC5D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AA2BD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,IAAI,CA0G1F"}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mailgun Webhook Routes — optional route factory for delivery tracking.
|
|
3
|
-
*
|
|
4
|
-
* Usage:
|
|
5
|
-
* import { addMailgunWebhookRoutes } from '@soulbatical/tetra-core';
|
|
6
|
-
* addMailgunWebhookRoutes(router, { signingKey: process.env.MAILGUN_WEBHOOK_SIGNING_KEY });
|
|
7
|
-
*
|
|
8
|
-
* @module @soulbatical/tetra-core/email
|
|
9
|
-
*/
|
|
10
|
-
import crypto from 'crypto';
|
|
11
|
-
function verifySignature(timestamp, token, signature, signingKey, maxAge) {
|
|
12
|
-
const currentTime = Date.now() / 1000;
|
|
13
|
-
const webhookTime = parseInt(timestamp, 10);
|
|
14
|
-
const timestampAge = currentTime - webhookTime;
|
|
15
|
-
// Reject timestamps too far in the future (clock skew tolerance: 5 seconds)
|
|
16
|
-
if (timestampAge < -5)
|
|
17
|
-
return false;
|
|
18
|
-
// Reject timestamps older than maxAge
|
|
19
|
-
if (timestampAge > maxAge)
|
|
20
|
-
return false;
|
|
21
|
-
// Verify HMAC signature using timing-safe comparison
|
|
22
|
-
const hmac = crypto.createHmac('sha256', signingKey);
|
|
23
|
-
const digest = hmac.update(timestamp + token).digest('hex');
|
|
24
|
-
if (digest.length !== signature.length)
|
|
25
|
-
return false;
|
|
26
|
-
return crypto.timingSafeEqual(Buffer.from(digest, 'hex'), Buffer.from(signature, 'hex'));
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Add Mailgun webhook route to a router.
|
|
30
|
-
* Handles: delivered, opened, clicked, bounced, failed, complained events.
|
|
31
|
-
* Updates email_logs table with delivery tracking data.
|
|
32
|
-
*/
|
|
33
|
-
export function addMailgunWebhookRoutes(router, config) {
|
|
34
|
-
const maxAge = config.maxTimestampAge ?? 30;
|
|
35
|
-
router.post('/mailgun', async (req, res) => {
|
|
36
|
-
try {
|
|
37
|
-
const event = req.body;
|
|
38
|
-
if (!event?.signature || !event?.['event-data']) {
|
|
39
|
-
res.status(400).json({ error: 'Invalid webhook structure' });
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
// Verify signature
|
|
43
|
-
const { timestamp, token, signature } = event.signature;
|
|
44
|
-
if (!config.skipVerification) {
|
|
45
|
-
if (!config.signingKey) {
|
|
46
|
-
console.error('[email/webhook] MAILGUN_WEBHOOK_SIGNING_KEY not configured');
|
|
47
|
-
res.status(401).json({ error: 'Webhook signing key not configured' });
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
if (!verifySignature(timestamp, token, signature, config.signingKey, maxAge)) {
|
|
51
|
-
console.warn('[email/webhook] Invalid Mailgun webhook signature');
|
|
52
|
-
res.status(401).json({ error: 'Invalid signature' });
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
const eventData = event['event-data'];
|
|
57
|
-
const eventType = eventData.event;
|
|
58
|
-
const recipient = eventData.recipient?.toLowerCase();
|
|
59
|
-
const eventTimestamp = new Date(eventData.timestamp * 1000).toISOString();
|
|
60
|
-
if (!recipient) {
|
|
61
|
-
res.status(200).json({ message: 'No recipient' });
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
// Find most recent email log for this recipient
|
|
65
|
-
const { data: emailLog } = await config.supabase
|
|
66
|
-
.from('email_logs')
|
|
67
|
-
.select('id, status, opened_at, clicked_at')
|
|
68
|
-
.eq('to_email', recipient)
|
|
69
|
-
.order('created_at', { ascending: false })
|
|
70
|
-
.limit(1)
|
|
71
|
-
.single();
|
|
72
|
-
if (!emailLog) {
|
|
73
|
-
res.status(200).json({ message: 'No matching log' });
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
// Build updates based on event type
|
|
77
|
-
const updates = {};
|
|
78
|
-
switch (eventType) {
|
|
79
|
-
case 'delivered':
|
|
80
|
-
updates.status = 'delivered';
|
|
81
|
-
updates.delivered_at = eventTimestamp;
|
|
82
|
-
break;
|
|
83
|
-
case 'opened':
|
|
84
|
-
if (!emailLog.opened_at)
|
|
85
|
-
updates.opened_at = eventTimestamp;
|
|
86
|
-
if (emailLog.status === 'sent' || emailLog.status === 'delivered') {
|
|
87
|
-
updates.status = 'opened';
|
|
88
|
-
}
|
|
89
|
-
break;
|
|
90
|
-
case 'clicked':
|
|
91
|
-
if (!emailLog.clicked_at)
|
|
92
|
-
updates.clicked_at = eventTimestamp;
|
|
93
|
-
updates.status = 'clicked';
|
|
94
|
-
break;
|
|
95
|
-
case 'bounced':
|
|
96
|
-
case 'failed':
|
|
97
|
-
updates.status = eventType;
|
|
98
|
-
updates.error_message =
|
|
99
|
-
eventData['delivery-status']?.message ||
|
|
100
|
-
eventData['delivery-status']?.description ||
|
|
101
|
-
`Email ${eventType}`;
|
|
102
|
-
break;
|
|
103
|
-
case 'complained':
|
|
104
|
-
updates.status = 'complained';
|
|
105
|
-
break;
|
|
106
|
-
default:
|
|
107
|
-
res.status(200).json({ message: 'ok' });
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
if (Object.keys(updates).length > 0) {
|
|
111
|
-
await config.supabase
|
|
112
|
-
.from('email_logs')
|
|
113
|
-
.update(updates)
|
|
114
|
-
.eq('id', emailLog.id);
|
|
115
|
-
}
|
|
116
|
-
res.status(200).json({ message: 'ok' });
|
|
117
|
-
}
|
|
118
|
-
catch (error) {
|
|
119
|
-
console.error('[email/webhook] Error processing webhook:', error);
|
|
120
|
-
// Return 200 to prevent Mailgun retries
|
|
121
|
-
res.status(200).json({ message: 'error logged' });
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
//# sourceMappingURL=webhookRoutes.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"webhookRoutes.js","sourceRoot":"","sources":["../../../src/shared/email/webhookRoutes.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MCP Online Module
|
|
3
|
-
*
|
|
4
|
-
* Provides everything needed to expose MCP tools over HTTP:
|
|
5
|
-
* - StreamableHTTP transport with Bearer token auth
|
|
6
|
-
* - Browser-based login flow for token acquisition
|
|
7
|
-
* - Token CRUD management
|
|
8
|
-
* - Usage stats / audit logging
|
|
9
|
-
* - Tenant isolation via AsyncLocalStorage
|
|
10
|
-
*
|
|
11
|
-
* Quick start:
|
|
12
|
-
* ```typescript
|
|
13
|
-
* import { addMcpRoutes, addMcpAuthRoutes, addMcpTokenRoutes, addMcpUsageRoutes } from '@soulbatical/tetra-core';
|
|
14
|
-
* import { Router } from 'express';
|
|
15
|
-
*
|
|
16
|
-
* const tokenPrefix = 'myapp_';
|
|
17
|
-
*
|
|
18
|
-
* // MCP endpoint (Bearer API token auth)
|
|
19
|
-
* const mcpRouter = Router();
|
|
20
|
-
* addMcpRoutes(mcpRouter, { tools, handlers, tokenPrefix });
|
|
21
|
-
* app.use('/api/mcp', mcpRouter);
|
|
22
|
-
*
|
|
23
|
-
* // Browser auth flow (public + JWT)
|
|
24
|
-
* const mcpAuthRouter = Router();
|
|
25
|
-
* addMcpAuthRoutes(mcpAuthRouter, { tokenPrefix });
|
|
26
|
-
* app.use('/api/mcp-auth', mcpAuthRouter);
|
|
27
|
-
*
|
|
28
|
-
* // Token management (JWT auth)
|
|
29
|
-
* const mcpTokensRouter = Router();
|
|
30
|
-
* addMcpTokenRoutes(mcpTokensRouter, { tokenPrefix });
|
|
31
|
-
* app.use('/api/mcp-tokens', mcpTokensRouter);
|
|
32
|
-
*
|
|
33
|
-
* // Usage stats (JWT auth)
|
|
34
|
-
* const mcpUsageRouter = Router();
|
|
35
|
-
* addMcpUsageRoutes(mcpUsageRouter);
|
|
36
|
-
* app.use('/api/mcp-usage', mcpUsageRouter);
|
|
37
|
-
* ```
|
|
38
|
-
*
|
|
39
|
-
* Database: requires `mcp_api_tokens` and `mcp_audit_log` tables.
|
|
40
|
-
* See migrations/ directory for SQL.
|
|
41
|
-
*/
|
|
42
|
-
export { addMcpRoutes } from './mcp-routes.js';
|
|
43
|
-
export { addMcpAuthRoutes } from './mcp-auth-routes.js';
|
|
44
|
-
export { addMcpTokenRoutes } from './mcp-tokens-routes.js';
|
|
45
|
-
export { addMcpUsageRoutes } from './mcp-usage-routes.js';
|
|
46
|
-
export { getMcpOrganizationId, getMcpTenantContext, runWithMcpTenant, validateMcpApiToken, generateMcpApiToken } from './tenant-context.js';
|
|
47
|
-
export type { GenerateMcpApiTokenOptions } from './tenant-context.js';
|
|
48
|
-
export { mcpDB, mcpScopedDB } from './mcp-db.js';
|
|
49
|
-
export type { McpDBResult, McpDBLocalResult, McpDBOptions } from './mcp-db.js';
|
|
50
|
-
export type { McpRoutesConfig, McpAuthRoutesConfig, McpToolDefinition, McpToolResult, McpToolHandler, TenantContext } from './types.js';
|
|
51
|
-
//# sourceMappingURL=index.d.ts.map
|