Skip to content
API reference

carrier

Import
import * as api from "@fungi.computer/carrier";
Kind Export Description
class CarrierError Stable failures omit email bodies, tokens and raw provider errors.
type alias Carrier Durable email submission and its host-driven recovery door.
type alias Address One recipient address; display names remain part of the requested envelope.
type alias Email Common content and envelope for one Email.
type alias Submission Source identity and expiry belong to the notification’s producer.
type alias Message A recipient Message is distinct from its Email and provider request.
type alias ProviderRejection A provider’s definite refusal of a whole request: retryable or final.
type alias Receipt Durable submission and aggregate dispatch evidence, without credential content. refused means Carrier’s per-recipient cap declined the submission before any provider attempt; rejected means the provider definitely refused it (a permanent rejection, or temporary rejections until retries ran out). providerRejection is the last provider refusal, also while a temporary rejection waits queued for its retry.
type alias SendEvidence One transport invocation reports only the evidence it obtained. Report provider_rejected only for a documented refusal of the whole request before acceptance; cause is an optional sanitized provider code for logs.
type alias Host Mechanical host capabilities; commit must durably arm a wake with its mutation.
type alias Options Configure a durable owner; business validity remains with the source.
constant CarrierStatusSchema Carrier’s aggregate dispatch states at both storage and read boundaries.
function createCarrier() Construct exactly one owner per store/runtime lifetime. A replacement may be opened only after its predecessor has stopped; simultaneous owners of the same store are unsupported. Native adapters supply their runtime ownership.

Stable failures omit email bodies, tokens and raw provider errors.

  • YieldableError<this> & object & Readonly<{ code: "conflict" | "invalid_input" | "unavailable"; message: string; }>
Signature
new CarrierError(code): CarrierError;
Parameter Type
code "conflict" | "invalid_input" | "unavailable"

CarrierError

Signature
Data.TaggedError("CarrierError")<{
readonly code: "invalid_input" | "conflict" | "unavailable";
readonly message: string;
}>.constructor
Signature
readonly code: "conflict" | "invalid_input" | "unavailable";
Signature
Data.TaggedError("CarrierError").code;
Signature
message: string;
Signature
Data.TaggedError("CarrierError").message;
Signature
type Carrier = Readonly<{
send: (submission) => Promise<Receipt>;
get: (id) => Promise<Receipt | undefined>;
tick: () => Promise<void>;
hasPendingWork: () => Promise<boolean>;
}>;

Durable email submission and its host-driven recovery door.


Signature
type Address =
| string
| Readonly<{
email: string;
name: string;
}>;

One recipient address; display names remain part of the requested envelope.


Signature
type Email = Readonly<{
from: Address;
to?: readonly Address[];
cc?: readonly Address[];
bcc?: readonly Address[];
subject: string;
html?: string;
text?: string;
headers?: Readonly<Record<string, string>>;
}>;

Common content and envelope for one Email.


Submissiontype alias

Section titled “Submission”
Signature
type Submission = Email &
Readonly<{
id: string;
sendBefore?: number;
}>;

Source identity and expiry belong to the notification’s producer.


Signature
type Message = Readonly<{
id: string;
recipient: string;
roles: readonly ("to" | "cc" | "bcc")[];
status: "unconfirmed";
}>;

A recipient Message is distinct from its Email and provider request.


ProviderRejectiontype alias

Section titled “ProviderRejection”
Signature
type ProviderRejection = Readonly<{
code: string;
class: "permanent" | "temporary";
}>;

A provider’s definite refusal of a whole request: retryable or final.


Signature
type Receipt = Readonly<{
id: string;
status: Schema.Schema.Type<typeof CarrierStatusSchema>;
providerMessageId?: string;
providerRejection?: ProviderRejection;
messages: readonly Message[];
}>;

Durable submission and aggregate dispatch evidence, without credential content. refused means Carrier’s per-recipient cap declined the submission before any provider attempt; rejected means the provider definitely refused it (a permanent rejection, or temporary rejections until retries ran out). providerRejection is the last provider refusal, also while a temporary rejection waits queued for its retry.


SendEvidencetype alias

Section titled “SendEvidence”
Signature
type SendEvidence =
| Readonly<{
kind: "provider_accepted";
providerMessageId: string;
}>
| (Readonly<{
kind: "provider_rejected";
}> &
ProviderRejection)
| Readonly<{
kind: "outcome_unknown";
cause?: string;
}>;

One transport invocation reports only the evidence it obtained. Report provider_rejected only for a documented refusal of the whole request before acceptance; cause is an optional sanitized provider code for logs.


Signature
type Host = Readonly<{
commit: <A>(mutation) => Promise<A>;
requestWake: () => Promise<void>;
}>;

Mechanical host capabilities; commit must durably arm a wake with its mutation.


Signature
type Options = Readonly<{
storage: WatchdogSqliteOwner;
host: Host;
now: () => number;
canSend?: (emailId) => Promise<boolean>;
transport: (email) => Promise<SendEvidence>;
}>;

Configure a durable owner; business validity remains with the source.

CarrierStatusSchemaconstant

Section titled “CarrierStatusSchema”
Signature
const CarrierStatusSchema: Literals<
readonly [
"queued",
"dispatching",
"provider_accepted",
"outcome_unknown",
"rejected",
"refused",
"expired",
"superseded",
]
>;

Carrier’s aggregate dispatch states at both storage and read boundaries.

createCarrier()function

Section titled “createCarrier()”
Signature
function createCarrier(options): Promise<Readonly<{
send: (submission) => Promise<Readonly<{
id: string;
status: | "expired"
| "rejected"
| "queued"
| "outcome_unknown"
| "dispatching"
| "provider_accepted"
| "refused"
| "superseded";
providerMessageId?: string;
providerRejection?: Readonly<{
code: string;
class: ... | ...;
}>;
messages: readonly Readonly<{
id: string;
recipient: string;
roles: readonly ...[];
status: "unconfirmed";
}>[];
}>>;
get: (id) => Promise<
| Readonly<{
id: string;
status: | "expired"
| "rejected"
| "queued"
| "outcome_unknown"
| "dispatching"
| "provider_accepted"
| "refused"
| "superseded";
providerMessageId?: string;
providerRejection?: Readonly<{
code: ...;
class: ...;
}>;
messages: readonly Readonly<{
id: ...;
recipient: ...;
roles: ...;
status: ...;
}>[];
}>
| undefined>;
tick: () => Promise<void>;
hasPendingWork: () => Promise<boolean>;
}>>;

Construct exactly one owner per store/runtime lifetime. A replacement may be opened only after its predecessor has stopped; simultaneous owners of the same store are unsupported. Native adapters supply their runtime ownership.

Parameter Type
options Options

Promise<Readonly<{ send: (submission) => Promise<Readonly<{ id: string; status: | "expired" | "rejected" | "queued" | "outcome_unknown" | "dispatching" | "provider_accepted" | "refused" | "superseded"; providerMessageId?: string; providerRejection?: Readonly<{ code: string; class: … | …; }>; messages: readonly Readonly<{ id: string; recipient: string; roles: readonly …[]; status: "unconfirmed"; }>[]; }>>; get: (id) => Promise< | Readonly<{ id: string; status: | "expired" | "rejected" | "queued" | "outcome_unknown" | "dispatching" | "provider_accepted" | "refused" | "superseded"; providerMessageId?: string; providerRejection?: Readonly<{ code: …; class: …; }>; messages: readonly Readonly<{ id: …; recipient: …; roles: …; status: …; }>[]; }> | undefined>; tick: () => Promise<void>; hasPendingWork: () => Promise<boolean>; }>>