Something went wrong. Try again.
Monorepo for Tangled forked from tangled.org/core
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091import { authedGet, authedPost, type DeliberiContext } from "#lib/api/deliberi.ts";import { buildUrl } from "#lib/api/_request.ts";import { ClientResponseError } from "#lib/api/client.ts";import { nsidOf } from "#lib/api/syntax.ts";
export interface ListEmailItem { address: string; verified: boolean; primary: boolean; createdAt: string;}
const LIST_EMAILS = nsidOf("org.tangled.temp.account.listEmails");const ADD_EMAIL = nsidOf("org.tangled.temp.account.addEmail");const VERIFY_EMAIL = nsidOf("org.tangled.temp.account.verifyEmail");const DELETE_EMAIL = nsidOf("org.tangled.temp.account.deleteEmail");const SET_PRIMARY_EMAIL = nsidOf("org.tangled.temp.account.setPrimaryEmail");
export const listEmails = (ctx: DeliberiContext): Promise<{ emails: ListEmailItem[] }> => authedGet(ctx, LIST_EMAILS);
export const addEmail = (ctx: DeliberiContext, email: string): Promise<void> => authedPost(ctx, ADD_EMAIL, { email }).then(() => undefined);
export class VerificationError extends Error { constructor( message: string, readonly kind: "invalid" | "unavailable" ) { super(message); }}
export const verifyEmailByToken = async ( serviceUrl: string, token: string, fetchFn: typeof globalThis.fetch = fetch): Promise<{ email: string }> => { const response = await fetchFn(buildUrl(serviceUrl, VERIFY_EMAIL), { method: "POST", headers: { "content-type": "application/json", accept: "application/json" }, body: JSON.stringify({ token }) }); if (response.status === 400) { throw new VerificationError( "The verification link is invalid or has already been used.", "invalid" ); } if (!response.ok) { throw new VerificationError( `Could not reach the verification service (${response.status}).`, "unavailable" ); } const text = await response.text(); return text ? JSON.parse(text) : { email: "" };};
export const emailServiceError = (cause: unknown): string => { if (cause instanceof ClientResponseError) { if (cause.status === 401 || cause.status === 403) { return "Unable to confirm your session with the email service. Sign out, sign back in, and try again."; } if (cause.status >= 500) return "Unable to reach the email service. Try again in a moment."; if (cause.error === "InvalidEmail") { return "Check the email address. It needs a domain that can receive mail."; } const description = cause.description?.trim(); if (!description) return "Unable to update your emails. Try again."; const sentence = description.charAt(0).toUpperCase() + description.slice(1); return /[.!?]$/.test(sentence) ? sentence : `${sentence}.`; } if (cause instanceof TypeError) { return "Unable to reach the email service. Check your connection and try again."; } return cause instanceof Error ? cause.message : String(cause);};
export const deleteEmail = (ctx: DeliberiContext, email: string): Promise<void> => authedPost(ctx, DELETE_EMAIL, { email }).then(() => undefined);
export const setPrimaryEmail = (ctx: DeliberiContext, email: string): Promise<void> => authedPost(ctx, SET_PRIMARY_EMAIL, { email }).then(() => undefined);
export const markPrimary = (rows: ListEmailItem[], address: string): ListEmailItem[] => rows.map((row) => ({ ...row, primary: row.address === address }));
export const removeEmailRow = (rows: ListEmailItem[], address: string): ListEmailItem[] => rows.filter((row) => row.address !== address);