Extract emails into separate package with clean interface
- Create packages/emails/ with EmailClient interface abstraction - Wrap Postmark ServerClient in adapter for clean typing - Add createLoggingEmailClient for dev mode (logs to console) - Split email templates into individual files with full test coverage - Update api-server to use new package via context injection - Remove EMAIL_DEV_MODE - now uses POSTMARK_API_KEY presence - Delete apps/api-server/src/utils/email.ts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
54
packages/emails/src/helpers.ts
Normal file
54
packages/emails/src/helpers.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { DurationFormat } from "@formatjs/intl-durationformat";
|
||||
import type { OrgRole } from "@reviq/db-schema";
|
||||
|
||||
export function buildUrl(
|
||||
baseUrl: string,
|
||||
path: string,
|
||||
params: Record<string, string>,
|
||||
): string {
|
||||
const url = new URL(path, baseUrl);
|
||||
for (const [key, value] of Object.entries(params)) {
|
||||
url.searchParams.set(key, value);
|
||||
}
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
export function escapeHtml(unsafe: string): string {
|
||||
return unsafe
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
|
||||
const durationFormatter = new DurationFormat("en", { style: "long" });
|
||||
|
||||
export function formatExpiryHours(hours: number): string {
|
||||
return durationFormatter.format({ hours });
|
||||
}
|
||||
|
||||
export function formatExpiryMinutes(minutes: number): string {
|
||||
return durationFormatter.format({ minutes });
|
||||
}
|
||||
|
||||
export function formatExpiryDays(days: number): string {
|
||||
return durationFormatter.format({ days });
|
||||
}
|
||||
|
||||
const roleLabels: Record<OrgRole, string> = {
|
||||
owner: "Owner",
|
||||
admin: "Admin",
|
||||
member: "Member",
|
||||
};
|
||||
|
||||
export function formatRoleDisplay(role: OrgRole): string {
|
||||
return roleLabels[role];
|
||||
}
|
||||
|
||||
export function getArticleForRole(role: OrgRole): string {
|
||||
if (role === "owner" || role === "admin") {
|
||||
return "an";
|
||||
}
|
||||
return "a";
|
||||
}
|
||||
Reference in New Issue
Block a user