feat(db): mesh data model — meshes, members, invites, audit log
- pgSchema "mesh" with 4 tables isolating the peer mesh domain - Enums: visibility, transport, tier, role - audit_log is metadata-only (E2E encryption enforced at broker/client) - Cascade on mesh delete, soft-delete via archivedAt/revokedAt Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
38
packages/email/src/server.ts
Normal file
38
packages/email/src/server.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { logger } from "@turbostarter/shared/logger";
|
||||
|
||||
import { send } from "./providers";
|
||||
import { getTemplate } from "./templates";
|
||||
|
||||
import type { EmailTemplate, EmailVariables } from "./types";
|
||||
|
||||
const sendEmail = async <T extends EmailTemplate>({
|
||||
to,
|
||||
template,
|
||||
locale,
|
||||
variables,
|
||||
}: {
|
||||
to: string;
|
||||
template: T;
|
||||
variables: EmailVariables[T];
|
||||
locale?: string;
|
||||
}) => {
|
||||
logger.info(`Sending email ${template} to ${to}`);
|
||||
|
||||
try {
|
||||
const { html, text, subject } = await getTemplate({
|
||||
id: template,
|
||||
variables,
|
||||
locale,
|
||||
});
|
||||
|
||||
const result = await send({ to, subject, html, text });
|
||||
logger.info(`Email sent successfully to ${to}`);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
logger.error(error, `Failed to send email ${template} to ${to}`);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export { sendEmail };
|
||||
Reference in New Issue
Block a user