import accounts from '../config/account.json' with { type: 'json' } import dkim from '../config/dkim.json' with { type: 'json' } export type AddressString = `${string}@${string}.${string}` export class Contact { #name: string #address: AddressString constructor( { name, address }: { name: string address: AddressString }, ) { this.#name = name this.#address = address } static expand(shortName: string): Contact { if (!(shortName in accounts)) { throw new Error('unknown short name contact') } const { name, address } = accounts[shortName as keyof typeof accounts] if (typeof name !== 'string') { throw new SyntaxError( `missing key "name" in contact short name config for "${shortName}"`, ) } if (typeof address !== 'string') { throw new SyntaxError( `missing key "address" in contact short name config for "${shortName}"`, ) } const addressRegExp = new RegExp(String.raw`\w+@(\w+\.)?${dkim.domainName}`) if (!(addressRegExp.test(address))) { throw new SyntaxError( `invalid "address" in contact short name config for "${shortName}"`, ) } //@ts-ignore checked against regex return new Contact({ name, address }) } static fromString(raw: string): Contact { const [_, name, address] = raw.match(/(.*)<(\S+@\S+\.\S+)>/)?.map((match) => match.trim()) ?? [] if (typeof address !== 'string') { throw new Error('address is empty') } //@ts-ignore checked against regex return new Contact({ name, address }) } toString(): string { return `${this.#name} <${this.#address}>` } toJSON(): { name: string; address: AddressString } { return { name: this.#name, address: this.#address, } as const } get name(): string { return this.#name } get address(): AddressString { return this.#address } }