UNPKG

@lusc/fastmail-masked-email

Version:

A library for creating, deleting, and updating Fastmail masked emails

199 lines 6.58 kB
import { array as zArray, null as zNull, object as zObject, record as zRecord, string as zString, unknown as zUnknown, } from 'zod'; import { MASKED_EMAIL_CALLS } from './constants.js'; import { apiRequest } from './http.js'; import { createOptionsSchema, maskedEmailStateSchema, optionsSchema, } from './schemas.js'; import { getSession } from './session.js'; const maskedEmailReducedDetailsSchema = zObject({ createdBy: zString(), createdAt: zString(), id: zString(), url: zString().or(zNull().transform(() => undefined)), lastMessageAt: zString().or(zNull().transform(() => undefined)), email: zString().regex(/^[^@]+@[^@]+\.[^@]+$/), }); const maskedEmailDetailsSchema = maskedEmailReducedDetailsSchema.and(zObject({ forDomain: zString(), description: zString(), state: maskedEmailStateSchema, })); export class MaskedEmail { details; session; static async create(options_ = {}, session_) { let options; let session; if ('apiToken' in options_) { session = options_; options = createOptionsSchema.parse({}); } else { options = createOptionsSchema.parse(options_); session = session_ ?? (await getSession()); } const { accountId } = session; const requestId = Math.random().toString(36).slice(2); const details = await apiRequest({ session, method: MASKED_EMAIL_CALLS.set, body: { accountId, create: { [requestId]: options, }, }, schema: zObject({ created: zObject({ [requestId]: maskedEmailReducedDetailsSchema, }), }).transform(o => ({ ...o.created[requestId], forDomain: options.forDomain ?? '', description: options.description ?? '', state: options.state, })), action: 'MaskedEmail.create', }); return new MaskedEmail(details, session); } static async findById(id, session) { const emails = await this.getAllEmails([id], session); if (emails.length === 0) { throw new Error(`Email with id "${id}" was not found`); } return emails[0]; } static async findByEmail(emailAddress, session) { const allEmails = await this.getAllEmails(undefined, session); for (const me of allEmails) { if (me.email === emailAddress) { return me; } } throw new Error(`No masked email found using address "${emailAddress}".`); } static async getAllEmails(ids, session_) { let session; if (ids && 'apiToken' in ids) { session = ids; ids = undefined; } session ??= session_ ?? (await getSession()); if (ids?.length === 0) { ids = undefined; } const { accountId } = session; return apiRequest({ session, method: MASKED_EMAIL_CALLS.get, body: { accountId, ids }, schema: zObject({ accountId: zString(), list: zArray(maskedEmailDetailsSchema), }).transform(o => o.list.map(details => new MaskedEmail(details, session))), action: 'MaskedEmail.getAllEmails', }); } constructor(details, session) { this.details = details; this.session = session; } get email() { return this.details.email; } get id() { return this.details.id; } get createdAt() { return new Date(this.details.createdAt); } get createdBy() { return this.details.createdBy; } get lastMessageAt() { return this.details.lastMessageAt ? new Date(this.details.lastMessageAt) : undefined; } get url() { return this.details.url; } get forDomain() { return this.details.forDomain ?? ''; } get description() { return this.details.description; } get state() { return this.details.state; } async update(options) { options = optionsSchema.parse(options); const { accountId } = this.session; const response = await apiRequest({ session: this.session, method: MASKED_EMAIL_CALLS.set, body: { accountId, update: { [this.id]: options, }, }, schema: zObject({ updated: zUnknown(), notUpdated: zRecord(zObject({ description: zString(), type: zString(), })).optional(), }), action: 'MaskedEmail.update', }); if (response.notUpdated && this.id in response.notUpdated) { const { type } = response.notUpdated[this.id]; throw new Error('Could not update ' + this.id + ' (' + type + ').'); } this.details.forDomain = options.forDomain ?? this.details.forDomain; this.details.description = options.description ?? this.details.description; this.details.state = options.state ?? this.details.state; return this; } async delete() { return this.update({ state: 'deleted', }); } async disable() { return this.update({ state: 'disabled', }); } async enable() { return this.update({ state: 'enabled', }); } async permanentlyDelete() { const { accountId } = this.session; const response = await apiRequest({ session: this.session, method: MASKED_EMAIL_CALLS.set, body: { accountId, destroy: [this.id], }, action: 'MaskedEmail#permanentlyDelete', schema: zObject({ destroyed: zArray(zString()), notDestroyed: zRecord(zObject({ type: zString(), description: zString(), subType: zString(), })).optional(), }), }); if (response.notDestroyed) { const reason = response.notDestroyed[this.id]; throw new Error(`${reason.type}(${reason.subType}): ${reason.description}`); } } } //# sourceMappingURL=masked-email.js.map