chore: bunch of improvements
All checks were successful
JS Unit Tests / test (pull_request) Successful in 33s
Build Test / test (pull_request) Successful in 36s
PHP Unit Tests / test (pull_request) Successful in 1m12s

Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
2026-04-23 22:00:50 -04:00
parent b617234b40
commit 3362afb7ec
28 changed files with 1717 additions and 1297 deletions

View File

@@ -1,15 +1,235 @@
/**
* Message and MessagePart model classes
*/
import type {
MessageAddressInterface,
MessageInterface,
MessageModelInterface,
MessagePartInterface,
MessagePartModelInterface
} from "@/types/message";
import type { MessageInterface, MessagePartInterface } from "@/types/message";
/**
* Message class for working with message objects
*/
export class MessageObject implements MessageModelInterface {
_data: MessageInterface;
_body: MessagePartObject | null = null;
constructor() {
this._data = {
'@type': 'mail:message',
};
this._body = null;
}
fromJson(data: MessageInterface): MessageObject {
this._data = data;
return this;
}
toJson(): MessageInterface {
const json = {
...this._data
};
if (this._body) {
json.body = this._body.toJson();
}
return json;
}
clone(): MessageObject {
const cloned = new MessageObject();
cloned._data = {
...this._data,
};
if (this._body) {
cloned._body = this._body.clone();
}
return cloned;
}
/** Properties */
get urid(): string | null{
return this._data.urid ?? null;
}
get size(): number {
return this._data.size ?? 0;
}
get receivedDate(): string | null {
return this._data.receivedDate ?? null;
}
get sentDate(): string | null {
return this._data.sentDate ?? null;
}
get date(): string | null {
return this._data.date ?? null;
}
get subject(): string | null {
return this._data.subject ?? null;
}
get snippet(): string | null {
return this._data.snippet ?? null;
}
get from(): MessageAddressObject | null {
return this._data.from ? new MessageAddressObject(this._data.from) : null;
}
get to(): Array<MessageAddressObject> | null {
return this._data.to ? this._data.to.map(addr => new MessageAddressObject(addr)) : null;
}
get cc(): Array<MessageAddressObject> | null {
return this._data.cc ? this._data.cc.map(addr => new MessageAddressObject(addr)) : null;
}
get bcc(): Array<MessageAddressObject> | null {
return this._data.bcc ? this._data.bcc.map(addr => new MessageAddressObject(addr)) : null;
}
get replyTo(): Array<MessageAddressObject> | null {
return this._data.replyTo ? this._data.replyTo.map(addr => new MessageAddressObject(addr)) : null;
}
get flags(): { read?: boolean; flagged?: boolean; answered?: boolean; draft?: boolean } | {} {
return this._data.flags ?? {};
}
get body(): MessagePartObject | null {
if (this._body) {
return this._body;
}
else if (this._data.body) {
this._body = new MessagePartObject(this._data.body);
return this._body;
}
return null;
}
get attachments(): Array<MessagePartObject> {
return this._data.attachments ? this._data.attachments.map(att => new MessagePartObject(att)) : [];
}
/** Helper methods */
get isRead(): boolean {
return this._data.flags?.read ?? false;
}
get isFlagged(): boolean {
return this._data.flags?.flagged ?? false;
}
get isAnswered(): boolean {
return this._data.flags?.answered ?? false;
}
get isDraft(): boolean {
return this._data.flags?.draft ?? false;
}
get hasAttachments(): boolean {
return (this._data.attachments?.length ?? 0) > 0;
}
hasRecipients(): boolean {
return (this._data.to?.length ?? 0) > 0
|| (this._data.cc?.length ?? 0) > 0
|| (this._data.bcc?.length ?? 0) > 0;
}
/** Body content helpers */
getBody(): MessagePartObject | null {
if (!this._body && this._data.body) {
this._body = new MessagePartObject(this._data.body);
}
return this._body;
}
hasContent(): boolean {
return !!this.getTextContent() || !!this.getHtmlContent();
}
hasTextContent(): boolean {
return !!this.getTextContent();
}
getTextContent(): string | null {
const bodyPart = this.getBody();
return bodyPart ? bodyPart.extractTextContent() : null;
}
hasHtmlContent(): boolean {
return !!this.getHtmlContent();
}
getHtmlContent(): string | null {
const bodyPart = this.getBody();
return bodyPart ? bodyPart.extractHtmlContent() : null;
}
findPartById(partId: string): MessagePartInterface | null {
const bodyPart = this.getBody();
return bodyPart ? bodyPart.findPartById(partId) : null;
}
findPartsByType(type: string): MessagePartInterface[] {
const bodyPart = this.getBody();
return bodyPart ? bodyPart.findPartsByType(type) : [];
}
}
export class MessageAddressObject implements MessageAddressInterface {
_data: MessageAddressInterface;
constructor(data: MessageAddressInterface) {
this._data = data;
}
fromJson(data: MessageAddressInterface): MessageAddressObject {
this._data = data;
return this;
}
toJson(): MessageAddressInterface {
return this._data;
}
clone(): MessageAddressObject {
return new MessageAddressObject({ ...this._data });
}
/** Properties */
get address(): string {
return this._data.address;
}
get label(): string | undefined {
return this._data.label;
}
}
/**
* MessagePart class for working with message body parts
*/
export class MessagePartObject {
export class MessagePartObject implements MessagePartModelInterface {
_data: MessagePartInterface;
_subParts: MessagePartObject[] = [];
constructor(data?: Partial<MessagePartInterface>) {
this._data = {
@@ -17,14 +237,14 @@ export class MessagePartObject {
blobId: data?.blobId ?? null,
size: data?.size ?? null,
name: data?.name ?? null,
type: data?.type ?? undefined,
type: data?.type ?? null,
charset: data?.charset ?? null,
disposition: data?.disposition ?? null,
cid: data?.cid ?? null,
language: data?.language ?? null,
location: data?.location ?? null,
content: data?.content ?? undefined,
subParts: data?.subParts ?? undefined,
content: data?.content ?? null,
subParts: data?.subParts ?? [],
};
}
@@ -34,7 +254,13 @@ export class MessagePartObject {
}
toJson(): MessagePartInterface {
return this._data;
const json = {
...this._data,
};
if (this._subParts.length > 0) {
json.subParts = this._subParts.map(subPart => subPart.toJson());
}
return json
}
clone(): MessagePartObject {
@@ -43,52 +269,59 @@ export class MessagePartObject {
/** Properties */
get partId(): string | null | undefined {
return this._data.partId;
get partId(): string | null {
return this._data.partId ?? null;
}
get blobId(): string | null | undefined {
return this._data.blobId;
get blobId(): string | null {
return this._data.blobId ?? null;
}
get size(): number | null | undefined {
return this._data.size;
get size(): number | null {
return this._data.size ?? null;
}
get name(): string | null | undefined {
return this._data.name;
get name(): string | null {
return this._data.name ?? null;
}
get type(): string | undefined {
return this._data.type;
get type(): string | null {
return this._data.type ?? null;
}
get charset(): string | null | undefined {
return this._data.charset;
get charset(): string | null {
return this._data.charset ?? null;
}
get disposition(): string | null | undefined {
return this._data.disposition;
get disposition(): string | null {
return this._data.disposition ?? null;
}
get cid(): string | null | undefined {
return this._data.cid;
get cid(): string | null {
return this._data.cid ?? null;
}
get language(): string | null | undefined {
return this._data.language;
get language(): string | null {
return this._data.language ?? null;
}
get location(): string | null | undefined {
return this._data.location;
get location(): string | null {
return this._data.location ?? null;
}
get content(): string | undefined {
return this._data.content;
get content(): string | null {
return this._data.content ?? null;
}
get subParts(): MessagePartInterface[] | undefined {
return this._data.subParts;
get subParts(): MessagePartModelInterface[] {
if (this._subParts) {
return this._subParts;
}
else if (this._data.subParts) {
this._subParts = this._data.subParts.map((subPart) => new MessagePartObject(subPart));
return this._subParts;
}
return [];
}
/** Helper methods */
@@ -98,7 +331,7 @@ export class MessagePartObject {
}
hasSubParts(): boolean {
return !!this._data.subParts && this._data.subParts.length > 0;
return this.subParts.length > 0;
}
isMultipart(): boolean {
@@ -206,171 +439,3 @@ export class MessagePartObject {
}
/**
* Message class for working with message objects
*/
export class MessageObject {
_data: MessageInterface;
_body: MessagePartObject | null = null;
constructor(data?: Partial<MessageInterface>) {
this._data = {
urid: data?.urid ?? undefined,
size: data?.size ?? undefined,
receivedDate: data?.receivedDate ?? undefined,
date: data?.date ?? undefined,
subject: data?.subject ?? undefined,
snippet: data?.snippet ?? undefined,
from: data?.from ?? undefined,
to: data?.to ?? [],
cc: data?.cc ?? [],
bcc: data?.bcc ?? [],
replyTo: data?.replyTo ?? [],
flags: data?.flags ?? {},
body: data?.body ?? undefined,
attachments: data?.attachments ?? [],
};
}
fromJson(data: MessageInterface): MessageObject {
this._data = data;
return this;
}
toJson(): MessageInterface {
return this._data;
}
clone(): MessageObject {
return new MessageObject(JSON.parse(JSON.stringify(this._data)));
}
/** Properties */
get urid(): string | undefined {
return this._data.urid;
}
get size(): number | undefined {
return this._data.size;
}
get receivedDate(): string | undefined {
return this._data.receivedDate;
}
get date(): string | undefined {
return this._data.date;
}
get subject(): string | undefined {
return this._data.subject;
}
get snippet(): string | undefined {
return this._data.snippet;
}
get from(): { address: string; label?: string } | undefined {
return this._data.from;
}
get to(): Array<{ address: string; label?: string }> | undefined {
return this._data.to;
}
get cc(): Array<{ address: string; label?: string }> | undefined {
return this._data.cc;
}
get bcc(): Array<{ address: string; label?: string }> | undefined {
return this._data.bcc;
}
get replyTo(): Array<{ address: string; label?: string }> | undefined {
return this._data.replyTo;
}
get flags(): { read?: boolean; flagged?: boolean; answered?: boolean; draft?: boolean } | undefined {
return this._data.flags;
}
get body(): MessagePartInterface | undefined {
return this._data.body;
}
get attachments(): MessageInterface['attachments'] {
return this._data.attachments;
}
/** Helper methods */
get isRead(): boolean {
return this._data.flags?.read ?? false;
}
get isFlagged(): boolean {
return this._data.flags?.flagged ?? false;
}
get isAnswered(): boolean {
return this._data.flags?.answered ?? false;
}
get isDraft(): boolean {
return this._data.flags?.draft ?? false;
}
get hasAttachments(): boolean {
return (this._data.attachments?.length ?? 0) > 0;
}
hasRecipients(): boolean {
return (this._data.to?.length ?? 0) > 0
|| (this._data.cc?.length ?? 0) > 0
|| (this._data.bcc?.length ?? 0) > 0;
}
/** Body content helpers */
getBody(): MessagePartObject | null {
if (!this._body && this._data.body) {
this._body = new MessagePartObject(this._data.body);
}
return this._body;
}
hasContent(): boolean {
return !!this.getTextContent() || !!this.getHtmlContent();
}
hasTextContent(): boolean {
return !!this.getTextContent();
}
getTextContent(): string | null {
const bodyPart = this.getBody();
return bodyPart ? bodyPart.extractTextContent() : null;
}
hasHtmlContent(): boolean {
return !!this.getHtmlContent();
}
getHtmlContent(): string | null {
const bodyPart = this.getBody();
return bodyPart ? bodyPart.extractHtmlContent() : null;
}
findPartById(partId: string): MessagePartInterface | null {
const bodyPart = this.getBody();
return bodyPart ? bodyPart.findPartById(partId) : null;
}
findPartsByType(type: string): MessagePartInterface[] {
const bodyPart = this.getBody();
return bodyPart ? bodyPart.findPartsByType(type) : [];
}
}