Packages

LiveView-style runtime for Gleam.

Current section

Files

Jump to
lightspeed src lightspeed integration mail.gleam
Raw

src/lightspeed/integration/mail.gleam

//// Mail integration patterns for ecosystem compatibility (M26).
import gleam/int
/// Mail backend profile.
pub type MailBackend {
InMemoryOutbox
SwooshBridge(module: String)
MixedMail(primary: String, fallback: String)
}
/// Delivery policy for one mail flow.
pub type DeliveryPolicy {
DeliveryPolicy(
max_retries: Int,
idempotency_key_required: Bool,
tenant_header_required: Bool,
)
}
/// One mail integration pattern.
pub type Pattern {
Pattern(name: String, backend: MailBackend, policy: DeliveryPolicy)
}
/// Transactional-mail integration pattern.
pub fn transactional_pattern() -> Pattern {
Pattern(
name: "transactional_mail",
backend: SwooshBridge(module: "MyApp.Mailer"),
policy: DeliveryPolicy(
max_retries: 5,
idempotency_key_required: True,
tenant_header_required: True,
),
)
}
/// Mixed-runtime digest-mail pattern.
pub fn digest_pattern() -> Pattern {
Pattern(
name: "digest_mail",
backend: MixedMail(primary: "Swoosh", fallback: "GleamOutbox"),
policy: DeliveryPolicy(
max_retries: 3,
idempotency_key_required: True,
tenant_header_required: True,
),
)
}
/// Local development mail pattern.
pub fn local_dev_pattern() -> Pattern {
Pattern(
name: "local_dev_mail",
backend: InMemoryOutbox,
policy: DeliveryPolicy(
max_retries: 1,
idempotency_key_required: True,
tenant_header_required: True,
),
)
}
/// Validate mail integration constraints.
pub fn valid(pattern: Pattern) -> Bool {
backend_valid(pattern.backend)
&& pattern.policy.max_retries > 0
&& pattern.policy.idempotency_key_required
&& pattern.policy.tenant_header_required
}
/// Stable backend label.
pub fn backend_label(backend: MailBackend) -> String {
case backend {
InMemoryOutbox -> "in_memory_outbox"
SwooshBridge(module) -> "swoosh_bridge:" <> module
MixedMail(primary, fallback) -> "mixed_mail:" <> primary <> ":" <> fallback
}
}
/// Stable pattern signature.
pub fn signature(pattern: Pattern) -> String {
"mail:"
<> pattern.name
<> "|backend="
<> backend_label(pattern.backend)
<> "|max_retries="
<> int.to_string(pattern.policy.max_retries)
<> "|idempotency_key_required="
<> bool_label(pattern.policy.idempotency_key_required)
<> "|tenant_header_required="
<> bool_label(pattern.policy.tenant_header_required)
}
/// Pattern backend.
pub fn backend(pattern: Pattern) -> MailBackend {
pattern.backend
}
/// Pattern name.
pub fn name(pattern: Pattern) -> String {
pattern.name
}
fn backend_valid(backend: MailBackend) -> Bool {
case backend {
InMemoryOutbox -> True
SwooshBridge(module) -> module != ""
MixedMail(primary, fallback) -> primary != "" && fallback != ""
}
}
fn bool_label(value: Bool) -> String {
case value {
True -> "true"
False -> "false"
}
}