alepha
Version:
Easy-to-use modern TypeScript framework for building many kind of applications.
551 lines • 26.1 kB
TypeScript
import { Alepha, KIND, Primitive, Static, StaticEncode, TObject } from "alepha";
import { DateTimeProvider } from "alepha/datetime";
import { EmailProvider } from "alepha/email";
import { SmsProvider } from "alepha/sms";
//#region ../../src/api/notifications/schemas/notificationPayloadSchema.d.ts
declare const notificationPayloadSchema: import("zod").ZodObject<{
type: import("zod").ZodEnum<{
email: "email";
sms: "sms";
}>;
template: import("zod").ZodString;
contact: import("zod").ZodString;
variables: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodAny>>;
category: import("zod").ZodOptional<import("zod").ZodString>;
critical: import("zod").ZodOptional<import("zod").ZodBoolean>;
sensitive: import("zod").ZodOptional<import("zod").ZodBoolean>;
lang: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod/v4/core").$strip>;
type NotificationPayload = Static<typeof notificationPayloadSchema>;
//#endregion
//#region ../../src/api/notifications/services/NotificationSenderService.d.ts
type NotificationMessageEmail = {
subject: string;
body: string | ((variables: any) => string);
};
type NotificationMessageSms = {
message: string | ((variables: any) => string);
};
declare class NotificationSenderService {
protected readonly alepha: Alepha;
protected readonly log: import("alepha/logger").Logger;
protected readonly emailProvider: EmailProvider;
protected readonly smsProvider: SmsProvider;
send(payload: NotificationPayload): Promise<{
type: "email";
to: string;
subject: string;
body: string;
message?: undefined;
} | {
subject?: undefined;
body?: undefined;
type: "sms";
to: string;
message: string;
} | undefined>;
renderSms(payload: NotificationPayload): {
to: string;
message: string;
};
renderEmail(payload: NotificationPayload): {
to: string;
subject: string;
body: string;
};
/**
* Pick the template's `translations` entry for the payload language:
* exact match ("fr-FR") first, then the base language ("fr"). Returns
* undefined when there is no match — callers fall back to the default
* (template-level) message.
*/
protected translation(options: {
translations?: Record<string, {
email?: unknown;
sms?: unknown;
} | undefined>;
}, lang?: string): {
email?: NotificationMessageEmail;
sms?: NotificationMessageSms;
} | undefined;
protected load(payload: NotificationPayload): {
template: NotificationPrimitive<import("alepha").TObject>;
variables: Record<string, any>;
contact: string;
};
}
//#endregion
//#region ../../src/api/notifications/jobs/NotificationJobs.d.ts
/**
* Notification jobs + runtime-editable retention.
*
* - `settings` — a `$parameter` exposing `retentionDays` that admins can
* update at runtime. Changes propagate across instances via the parameter
* pub/sub; the next purge run picks up the new value with no restart.
* - `sendNotification` — queue-mode, audit-oriented. Every execution is kept
* (`record: "all"`, `keep: { ok: 0, error: 0 }` disables the ring-buffer
* trim) so the audit trail survives even under heavy volume.
* - `purgeOldNotifications` — cron sweep that deletes notification execution
* rows whose `completedAt` is older than the current `retentionDays`.
*
* Cron expression note: the purge cron is declared statically (`0 3 * * *`)
* because some runtimes (Cloudflare Workers) freeze cron triggers at deploy
* time. The *retention window* is fully runtime-editable — that's the knob
* that actually matters for operators.
*/
declare class NotificationJobs {
protected readonly log: import("alepha/logger").Logger;
protected readonly dt: DateTimeProvider;
protected readonly notificationSenderService: NotificationSenderService;
protected readonly executions: import("alepha/orm").Repository<import("zod").ZodObject<{
id: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_PRIMARY_KEY>, typeof import("alepha/orm").PG_DEFAULT>;
createdAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_CREATED_AT>, typeof import("alepha/orm").PG_DEFAULT>;
updatedAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_UPDATED_AT>, typeof import("alepha/orm").PG_DEFAULT>;
jobName: import("zod").ZodString;
key: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
organizationId: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
status: import("alepha/orm").PgAttr<import("zod").ZodEnum<{
cancelled: "cancelled";
error: "error";
ok: "ok";
pending: "pending";
running: "running";
scheduled: "scheduled";
}>, typeof import("alepha/orm").PG_DEFAULT>;
priority: import("alepha/orm").PgAttr<import("zod").ZodInt, typeof import("alepha/orm").PG_DEFAULT>;
attempt: import("alepha/orm").PgAttr<import("zod").ZodInt, typeof import("alepha/orm").PG_DEFAULT>;
maxAttempts: import("alepha/orm").PgAttr<import("zod").ZodInt, typeof import("alepha/orm").PG_DEFAULT>;
payload: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodAny>>;
scheduledAt: import("zod").ZodOptional<import("zod").ZodString>;
startedAt: import("zod").ZodOptional<import("zod").ZodString>;
completedAt: import("zod").ZodOptional<import("zod").ZodString>;
error: import("zod").ZodOptional<import("zod").ZodString>;
logs: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodObject<{
level: import("zod").ZodEnum<{
DEBUG: "DEBUG";
ERROR: "ERROR";
INFO: "INFO";
SILENT: "SILENT";
TRACE: "TRACE";
WARN: "WARN";
}>;
message: import("zod").ZodString;
service: import("zod").ZodString;
module: import("zod").ZodString;
context: import("zod").ZodOptional<import("zod").ZodString>;
app: import("zod").ZodOptional<import("zod").ZodString>;
data: import("zod").ZodOptional<import("zod").ZodAny>;
timestamp: import("zod").ZodNumber;
}, import("zod/v4/core").$strip>>>;
triggeredBy: import("zod").ZodOptional<import("zod").ZodString>;
triggeredByName: import("zod").ZodOptional<import("zod").ZodString>;
cancelledBy: import("zod").ZodOptional<import("zod").ZodString>;
cancelledByName: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod/v4/core").$strip>>;
/** Runtime-editable config. Admins can change retentionDays without deploy. */
readonly settings: import("alepha/api/parameters").ParameterPrimitive<import("zod").ZodObject<{
retentionDays: import("zod").ZodInt;
}, import("zod/v4/core").$strip>>;
readonly sendNotification: import("alepha/api/jobs").JobPrimitive<import("zod").ZodObject<{
type: import("zod").ZodEnum<{
email: "email";
sms: "sms";
}>;
template: import("zod").ZodString;
contact: import("zod").ZodString;
variables: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodAny>>;
category: import("zod").ZodOptional<import("zod").ZodString>;
critical: import("zod").ZodOptional<import("zod").ZodBoolean>;
sensitive: import("zod").ZodOptional<import("zod").ZodBoolean>;
lang: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod/v4/core").$strip>>;
readonly purgeOldNotifications: import("alepha/api/jobs").JobPrimitive<import("alepha").ZType>;
}
//#endregion
//#region ../../src/api/notifications/controllers/AdminNotificationController.d.ts
declare class AdminNotificationController {
protected readonly url: string;
protected readonly group: string;
protected readonly alepha: Alepha;
protected readonly notificationJobs: NotificationJobs;
protected readonly executions: import("alepha/orm").Repository<import("zod").ZodObject<{
id: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_PRIMARY_KEY>, typeof import("alepha/orm").PG_DEFAULT>;
createdAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_CREATED_AT>, typeof import("alepha/orm").PG_DEFAULT>;
updatedAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_UPDATED_AT>, typeof import("alepha/orm").PG_DEFAULT>;
jobName: import("zod").ZodString;
key: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
organizationId: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
status: import("alepha/orm").PgAttr<import("zod").ZodEnum<{
cancelled: "cancelled";
error: "error";
ok: "ok";
pending: "pending";
running: "running";
scheduled: "scheduled";
}>, typeof import("alepha/orm").PG_DEFAULT>;
priority: import("alepha/orm").PgAttr<import("zod").ZodInt, typeof import("alepha/orm").PG_DEFAULT>;
attempt: import("alepha/orm").PgAttr<import("zod").ZodInt, typeof import("alepha/orm").PG_DEFAULT>;
maxAttempts: import("alepha/orm").PgAttr<import("zod").ZodInt, typeof import("alepha/orm").PG_DEFAULT>;
payload: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodAny>>;
scheduledAt: import("zod").ZodOptional<import("zod").ZodString>;
startedAt: import("zod").ZodOptional<import("zod").ZodString>;
completedAt: import("zod").ZodOptional<import("zod").ZodString>;
error: import("zod").ZodOptional<import("zod").ZodString>;
logs: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodObject<{
level: import("zod").ZodEnum<{
DEBUG: "DEBUG";
ERROR: "ERROR";
INFO: "INFO";
SILENT: "SILENT";
TRACE: "TRACE";
WARN: "WARN";
}>;
message: import("zod").ZodString;
service: import("zod").ZodString;
module: import("zod").ZodString;
context: import("zod").ZodOptional<import("zod").ZodString>;
app: import("zod").ZodOptional<import("zod").ZodString>;
data: import("zod").ZodOptional<import("zod").ZodAny>;
timestamp: import("zod").ZodNumber;
}, import("zod/v4/core").$strip>>>;
triggeredBy: import("zod").ZodOptional<import("zod").ZodString>;
triggeredByName: import("zod").ZodOptional<import("zod").ZodString>;
cancelledBy: import("zod").ZodOptional<import("zod").ZodString>;
cancelledByName: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod/v4/core").$strip>>;
protected get jobName(): string;
/**
* The tenant this request is acting in, when multi-tenant. The notification
* outbox (`job_executions`) is shared across tenants in a pooled worker, so
* every read/delete here is scoped to this org to prevent cross-tenant access.
* Undefined in single-tenant apps → no extra filter (all rows are this app's).
*/
protected get organizationId(): string | undefined;
/** True when `exec` belongs to the acting tenant (or the app is single-tenant). */
protected sameTenant(exec: {
organizationId?: string | null;
}): boolean;
readonly findNotifications: import("alepha/server").ActionPrimitiveFn<{
query: import("zod").ZodObject<{
page: import("zod").ZodOptional<import("zod").ZodDefault<import("zod").ZodInt>>;
size: import("zod").ZodOptional<import("zod").ZodDefault<import("zod").ZodInt>>;
sort: import("zod").ZodOptional<import("zod").ZodString>;
status: import("zod").ZodOptional<import("zod").ZodEnum<{
cancelled: "cancelled";
completed: "completed";
dead: "dead";
pending: "pending";
retrying: "retrying";
running: "running";
scheduled: "scheduled";
}>>;
}, import("zod/v4/core").$strip>;
response: import("zod").ZodObject<{
content: import("zod").ZodArray<import("zod").ZodObject<{
id: import("zod").ZodString;
createdAt: import("zod").ZodString;
status: import("zod").ZodString;
template: import("zod").ZodOptional<import("zod").ZodString>;
type: import("zod").ZodOptional<import("zod").ZodString>;
contact: import("zod").ZodOptional<import("zod").ZodString>;
category: import("zod").ZodOptional<import("zod").ZodString>;
critical: import("zod").ZodOptional<import("zod").ZodBoolean>;
sensitive: import("zod").ZodOptional<import("zod").ZodBoolean>;
startedAt: import("zod").ZodOptional<import("zod").ZodString>;
completedAt: import("zod").ZodOptional<import("zod").ZodString>;
error: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod/v4/core").$strip>>;
page: import("zod").ZodObject<{
number: import("zod").ZodInt;
size: import("zod").ZodInt;
offset: import("zod").ZodInt;
numberOfElements: import("zod").ZodInt;
totalElements: import("zod").ZodOptional<import("zod").ZodInt>;
totalPages: import("zod").ZodOptional<import("zod").ZodInt>;
isEmpty: import("zod").ZodBoolean;
isFirst: import("zod").ZodBoolean;
isLast: import("zod").ZodBoolean;
}, import("zod/v4/core").$strip>;
}, import("zod/v4/core").$strip>;
}>;
readonly getNotification: import("alepha/server").ActionPrimitiveFn<{
params: import("zod").ZodObject<{
id: import("zod").ZodString;
}, import("zod/v4/core").$strip>;
response: import("zod").ZodObject<{
id: import("zod").ZodString;
createdAt: import("zod").ZodString;
status: import("zod").ZodString;
template: import("zod").ZodOptional<import("zod").ZodString>;
type: import("zod").ZodOptional<import("zod").ZodString>;
contact: import("zod").ZodOptional<import("zod").ZodString>;
category: import("zod").ZodOptional<import("zod").ZodString>;
critical: import("zod").ZodOptional<import("zod").ZodBoolean>;
sensitive: import("zod").ZodOptional<import("zod").ZodBoolean>;
startedAt: import("zod").ZodOptional<import("zod").ZodString>;
completedAt: import("zod").ZodOptional<import("zod").ZodString>;
error: import("zod").ZodOptional<import("zod").ZodString>;
variables: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodAny>>;
rendered: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodAny>>;
logs: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodObject<{
level: import("zod").ZodEnum<{
DEBUG: "DEBUG";
ERROR: "ERROR";
INFO: "INFO";
SILENT: "SILENT";
TRACE: "TRACE";
WARN: "WARN";
}>;
message: import("zod").ZodString;
service: import("zod").ZodString;
module: import("zod").ZodString;
context: import("zod").ZodOptional<import("zod").ZodString>;
app: import("zod").ZodOptional<import("zod").ZodString>;
data: import("zod").ZodOptional<import("zod").ZodAny>;
timestamp: import("zod").ZodNumber;
}, import("zod/v4/core").$strip>>>;
}, import("zod/v4/core").$strip>;
}>;
readonly deleteNotification: import("alepha/server").ActionPrimitiveFn<{
params: import("zod").ZodObject<{
id: import("zod").ZodString;
}, import("zod/v4/core").$strip>;
response: import("zod").ZodObject<{
ok: import("zod").ZodBoolean;
id: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodInt]>>;
count: import("zod").ZodOptional<import("zod").ZodNumber>;
}, import("zod/v4/core").$strip>;
}>;
readonly deleteNotifications: import("alepha/server").ActionPrimitiveFn<{
body: import("zod").ZodObject<{
ids: import("zod").ZodArray<import("zod").ZodString>;
}, import("zod/v4/core").$strip>;
response: import("zod").ZodObject<{
deleted: import("zod").ZodArray<import("zod").ZodString>;
}, import("zod/v4/core").$strip>;
}>;
protected toResource(exec: Record<string, unknown>): {
id: unknown;
createdAt: unknown;
status: unknown;
template: unknown;
type: unknown;
contact: unknown;
category: unknown;
critical: unknown;
sensitive: unknown;
startedAt: unknown;
completedAt: unknown;
error: unknown;
};
protected toDetailResource(exec: Record<string, unknown>): {
id: unknown;
createdAt: unknown;
status: unknown;
template: unknown;
type: unknown;
contact: unknown;
category: unknown;
critical: unknown;
sensitive: unknown;
startedAt: unknown;
completedAt: unknown;
error: unknown;
variables: unknown;
logs: unknown;
};
}
//#endregion
//#region ../../src/api/notifications/primitives/$notification.d.ts
/**
* Creates a notification primitive for managing email/SMS notification templates.
*
* Provides type-safe, reusable notification templates with multi-language support,
* variable substitution, and categorization for different notification channels.
*
* @example
* ```ts
* class NotificationTemplates {
* welcomeEmail = $notification({
* name: "welcome-email",
* category: "onboarding",
* schema: z.object({ username: z.text(), activationLink: z.text() }),
* email: {
* subject: "Welcome to our platform!",
* body: (vars) => `Hello ${vars.username}, click: ${vars.activationLink}`
* }
* });
*
* async sendWelcome(user: User) {
* await this.welcomeEmail.push({
* variables: { username: user.name, activationLink: generateLink() },
* contact: user.email
* });
* }
* }
* ```
*/
declare const $notification: {
<T extends TObject>(options: NotificationPrimitiveOptions<T>): NotificationPrimitive<T>;
[KIND]: typeof NotificationPrimitive;
};
interface NotificationPrimitiveOptions<T extends TObject> extends NotificationMessage<T> {
name?: string;
description?: string;
category?: string;
critical?: boolean;
sensitive?: boolean;
translations?: {
[lang: string]: NotificationMessage<T>;
};
schema: T;
}
declare class NotificationPrimitive<T extends TObject> extends Primitive<NotificationPrimitiveOptions<T>> {
protected readonly notificationJobs: NotificationJobs;
get name(): string;
/**
* Recipient language for `translations` resolution. Explicit `lang` wins;
* otherwise the language is captured FROM THE CURRENT REQUEST at push time
* (the i18n `lang` cookie, then `Accept-Language`) — the send job may run
* out of request context, so this must be resolved here, not in the sender.
*/
protected resolveLang(explicit?: string): string | undefined;
push(options: NotificationPushOptions<T>): Promise<void>;
configure(options: Partial<NotificationPrimitiveOptions<T>>): void;
}
interface NotificationPushOptions<T extends TObject> {
variables: StaticEncode<T>;
contact: string;
/** Recipient language (e.g. "fr"); defaults to the current request's. */
lang?: string;
/**
* Owning tenant for this notification. Defaults to the tenant resolved for
* the current request. Pass it explicitly when sending from a context with no
* request tenant — e.g. a cron sweep that fans out across clubs (use the
* subject entity's `organizationId`) — so the row stays correctly org-scoped.
*/
organizationId?: string;
}
interface NotificationMessage<T extends TObject> {
email?: {
subject: string;
body: string | ((variables: Static<T>) => string);
};
sms?: {
message: string | ((variables: Static<T>) => string);
};
}
//#endregion
//#region ../../src/api/notifications/schemas/notificationContactPreferencesSchema.d.ts
declare const notificationContactPreferencesSchema: import("zod").ZodObject<{
language: import("zod").ZodOptional<import("zod").ZodString>;
exclude: import("zod").ZodArray<import("zod").ZodString>;
}, import("zod/v4/core").$strip>;
type NotificationContactPreferences = Static<typeof notificationContactPreferencesSchema>;
//#endregion
//#region ../../src/api/notifications/schemas/notificationContactSchema.d.ts
declare const notificationContactSchema: import("zod").ZodObject<{
email: import("zod").ZodOptional<import("zod").ZodString>;
phoneNumber: import("zod").ZodOptional<import("zod").ZodString>;
firstName: import("zod").ZodOptional<import("zod").ZodString>;
lastName: import("zod").ZodOptional<import("zod").ZodString>;
language: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod/v4/core").$strip>;
type NotificationContact = Static<typeof notificationContactSchema>;
//#endregion
//#region ../../src/api/notifications/schemas/notificationDetailResourceSchema.d.ts
declare const notificationDetailResourceSchema: import("zod").ZodObject<{
id: import("zod").ZodString;
createdAt: import("zod").ZodString;
status: import("zod").ZodString;
template: import("zod").ZodOptional<import("zod").ZodString>;
type: import("zod").ZodOptional<import("zod").ZodString>;
contact: import("zod").ZodOptional<import("zod").ZodString>;
category: import("zod").ZodOptional<import("zod").ZodString>;
critical: import("zod").ZodOptional<import("zod").ZodBoolean>;
sensitive: import("zod").ZodOptional<import("zod").ZodBoolean>;
startedAt: import("zod").ZodOptional<import("zod").ZodString>;
completedAt: import("zod").ZodOptional<import("zod").ZodString>;
error: import("zod").ZodOptional<import("zod").ZodString>;
variables: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodAny>>;
rendered: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodAny>>;
logs: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodObject<{
level: import("zod").ZodEnum<{
DEBUG: "DEBUG";
ERROR: "ERROR";
INFO: "INFO";
SILENT: "SILENT";
TRACE: "TRACE";
WARN: "WARN";
}>;
message: import("zod").ZodString;
service: import("zod").ZodString;
module: import("zod").ZodString;
context: import("zod").ZodOptional<import("zod").ZodString>;
app: import("zod").ZodOptional<import("zod").ZodString>;
data: import("zod").ZodOptional<import("zod").ZodAny>;
timestamp: import("zod").ZodNumber;
}, import("zod/v4/core").$strip>>>;
}, import("zod/v4/core").$strip>;
type NotificationDetailResource = Static<typeof notificationDetailResourceSchema>;
//#endregion
//#region ../../src/api/notifications/schemas/notificationQuerySchema.d.ts
declare const notificationQuerySchema: import("zod").ZodObject<{
page: import("zod").ZodOptional<import("zod").ZodDefault<import("zod").ZodInt>>;
size: import("zod").ZodOptional<import("zod").ZodDefault<import("zod").ZodInt>>;
sort: import("zod").ZodOptional<import("zod").ZodString>;
status: import("zod").ZodOptional<import("zod").ZodEnum<{
cancelled: "cancelled";
completed: "completed";
dead: "dead";
pending: "pending";
retrying: "retrying";
running: "running";
scheduled: "scheduled";
}>>;
}, import("zod/v4/core").$strip>;
type NotificationQuery = Static<typeof notificationQuerySchema>;
//#endregion
//#region ../../src/api/notifications/schemas/notificationResourceSchema.d.ts
declare const notificationResourceSchema: import("zod").ZodObject<{
id: import("zod").ZodString;
createdAt: import("zod").ZodString;
status: import("zod").ZodString;
template: import("zod").ZodOptional<import("zod").ZodString>;
type: import("zod").ZodOptional<import("zod").ZodString>;
contact: import("zod").ZodOptional<import("zod").ZodString>;
category: import("zod").ZodOptional<import("zod").ZodString>;
critical: import("zod").ZodOptional<import("zod").ZodBoolean>;
sensitive: import("zod").ZodOptional<import("zod").ZodBoolean>;
startedAt: import("zod").ZodOptional<import("zod").ZodString>;
completedAt: import("zod").ZodOptional<import("zod").ZodString>;
error: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod/v4/core").$strip>;
type NotificationResource = Static<typeof notificationResourceSchema>;
//#endregion
//#region ../../src/api/notifications/index.d.ts
/**
* User notification management.
*
* **Features:**
* - Notification definitions (email/SMS templates)
* - Delivery via `$job` with retry and audit trail (`record: "all"` + no ring buffer trim)
* - Runtime-editable retention window via `$parameter` — purge cron respects it live
* - Admin API for inspecting sent notifications
*
* **Delivery mode** is decided at runtime by the `$job` system:
* - If your app loads `AlephaApiJobsQueue` (and thus `AlephaQueue`), notifications
* go through the queue (best for high-volume systems).
* - Otherwise, notifications run in **direct** mode: pushed to the outbox table
* and processed in the same process right after the HTTP response is returned.
* The reconciliation sweep is the safety net for crashes / retries.
*
* Direct mode is the recommended default for small / cheap deployments
* (Cloudflare Workers, single-instance Node) — no queue infrastructure required.
*
* @module alepha.api.notifications
*/
declare const AlephaApiNotifications: import("alepha").Service<import("alepha").Module>;
//#endregion
export { $notification, AdminNotificationController, AlephaApiNotifications, NotificationContact, NotificationContactPreferences, NotificationDetailResource, NotificationJobs, NotificationMessage, NotificationPayload, NotificationPrimitive, NotificationPrimitiveOptions, NotificationPushOptions, NotificationQuery, NotificationResource, NotificationSenderService, notificationContactPreferencesSchema, notificationContactSchema, notificationDetailResourceSchema, notificationPayloadSchema, notificationQuerySchema, notificationResourceSchema };
//# sourceMappingURL=index.d.ts.map