/** * Class model for Service Interface */ import type { ServiceInterface, ServiceCapabilitiesInterface, ServiceLocation, ServiceModelInterface } from "@/types/service"; import { Identity } from './identity'; import { Location } from './location'; import { MutationProxy } from './mutation-proxy'; import { clonePlain } from './clone-plain'; export class ServiceObject implements ServiceModelInterface { private _original: ServiceInterface; private _mutated: Partial; private _mutationProxy = new MutationProxy(() => this._original, () => this._mutated); _data!: ServiceInterface; _location: Location | null | undefined = undefined; _identity: Identity | null | undefined = undefined; constructor() { this._original = { '@type': 'mail:service', version: 1, provider: '', identifier: null, label: null, enabled: false, capabilities: {} }; this._mutated = {}; this._data = this._mutationProxy.create(); } fromJson(data: ServiceInterface): ServiceObject { this._original = clonePlain(data); this._mutated = {}; this._data = this._mutationProxy.create(); this._location = undefined; this._identity = undefined; return this; } toJson(): ServiceInterface; toJson(delta: true): Partial; toJson(delta?: boolean): ServiceInterface | Partial { if (this._location !== undefined) { if (!delta) { // handled below to preserve full ServiceInterface typing } } if (delta) { const json: Partial = clonePlain(this._mutated); if (this._location?.mutated()) { json.location = this._location.toJson(true) as ServiceInterface['location']; } if (this._identity?.mutated()) { json.identity = this._identity.toJson(true) as ServiceInterface['identity']; } return json; } const json: ServiceInterface = { ...clonePlain(this._original), ...clonePlain(this._mutated), }; if (this._location !== undefined) { json.location = this._location ? this._location.toJson() : null; } if (this._identity !== undefined) { json.identity = this._identity ? this._identity.toJson() : null; } return json; } clone(): ServiceObject { return new ServiceObject().fromJson(this.toJson()); } mutated(): boolean { return Reflect.ownKeys(this._mutated).length > 0 || (this._location?.mutated() ?? false) || (this._identity?.mutated() ?? false); } capable(capability: keyof ServiceCapabilitiesInterface): boolean { const value = this._data.capabilities?.[capability]; return value !== undefined && value !== false; } capability(capability: keyof ServiceCapabilitiesInterface): any | null { if (this._data.capabilities) { return this._data.capabilities[capability]; } return null; } /** Immutable Properties */ get provider(): string { return this._data.provider; } get identifier(): string | number | null { return this._data.identifier; } get capabilities(): ServiceCapabilitiesInterface { return this._data.capabilities ?? {}; } get primaryAddress(): string | null { return this._data.primaryAddress ?? null; } set primaryAddress(value: string | null) { this._data.primaryAddress = value; } get secondaryAddresses(): string[] { return this._data.secondaryAddresses ?? []; } set secondaryAddresses(value: string[] | null) { this._data.secondaryAddresses = value; } /** Mutable Properties */ get label(): string | null { return this._data.label; } set label(value: string | null) { this._data.label = value; } get enabled(): boolean { return this._data.enabled; } set enabled(value: boolean) { this._data.enabled = value; } get location(): Location | null { if (this._location !== undefined) { return this._location; } if (this._data.location) { this._location = Location.fromJson(this._data.location as ServiceLocation); return this._location; } this._location = null; return null; } set location(value: Location | null) { this._location = value; } get identity(): Identity | null { if (this._identity !== undefined) { return this._identity; } if (this._data.identity) { this._identity = Identity.fromJson(this._data.identity); return this._identity; } this._identity = null; return null; } set identity(value: Identity | null) { this._identity = value; } get auxiliary(): Record { return this._data.auxiliary ?? {}; } set auxiliary(value: Record) { this._data.auxiliary = value; } }