feat: lots more improvements
JS Unit Tests / test (pull_request) Failing after 29s
Build Test / test (pull_request) Successful in 31s
PHP Unit Tests / test (pull_request) Successful in 1m12s

Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
2026-04-25 15:41:16 -04:00
parent 86e4772d45
commit 99a68737d1
26 changed files with 902 additions and 596 deletions
+73 -37
View File
@@ -10,15 +10,20 @@ import type {
} 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<ServiceInterface>;
private _mutationProxy = new MutationProxy<ServiceInterface>(() => this._original, () => this._mutated);
_data!: ServiceInterface;
_location: Location | null = null;
_identity: Identity | null = null;
_location: Location | null | undefined = undefined;
_identity: Identity | null | undefined = undefined;
constructor() {
this._data = {
this._original = {
'@type': 'mail:service',
version: 1,
provider: '',
@@ -27,43 +32,64 @@ export class ServiceObject implements ServiceModelInterface {
enabled: false,
capabilities: {}
};
this._mutated = {};
this._data = this._mutationProxy.create();
}
fromJson(data: ServiceInterface): ServiceObject {
this._data = data;
this._original = clonePlain(data);
this._mutated = {};
this._data = this._mutationProxy.create();
this._location = undefined;
this._identity = undefined;
return this;
}
toJson(): ServiceInterface {
const json = {
...this._data,
capabilities: this._data.capabilities ? { ...this._data.capabilities } : this._data.capabilities,
secondaryAddresses: this._data.secondaryAddresses ? [...this._data.secondaryAddresses] : this._data.secondaryAddresses,
auxiliary: this._data.auxiliary ? { ...this._data.auxiliary } : this._data.auxiliary,
};
if (this._location !== null) {
json.location = this._location.toJson();
toJson(): ServiceInterface;
toJson(delta: true): Partial<ServiceInterface>;
toJson(delta?: boolean): ServiceInterface | Partial<ServiceInterface> {
if (this._location !== undefined) {
if (!delta) {
// handled below to preserve full ServiceInterface typing
}
}
if (this._identity !== null) {
json.identity = this._identity.toJson();
if (delta) {
const json: Partial<ServiceInterface> = 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 {
const cloned = new ServiceObject();
cloned._data = {
...this._data,
capabilities: this._data.capabilities ? { ...this._data.capabilities } : this._data.capabilities,
secondaryAddresses: this._data.secondaryAddresses ? [...this._data.secondaryAddresses] : this._data.secondaryAddresses,
auxiliary: this._data.auxiliary ? { ...this._data.auxiliary } : this._data.auxiliary,
};
cloned._location = this._location ? this._location.clone() : null;
cloned._identity = this._identity ? this._identity.clone() : null;
return cloned;
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 {
@@ -96,10 +122,18 @@ export class ServiceObject implements ServiceModelInterface {
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 {
@@ -119,15 +153,16 @@ export class ServiceObject implements ServiceModelInterface {
}
get location(): Location | null {
if (this._location) {
if (this._location !== undefined) {
return this._location;
}
else if (this._location === null && this._data.location) {
const location = Location.fromJson(this._data.location as ServiceLocation);
this._location = location;
return location;
if (this._data.location) {
this._location = Location.fromJson(this._data.location as ServiceLocation);
return this._location;
}
this._location = null;
return null;
}
@@ -136,15 +171,16 @@ export class ServiceObject implements ServiceModelInterface {
}
get identity(): Identity | null {
if (this._identity) {
if (this._identity !== undefined) {
return this._identity;
}
else if (this._data.identity) {
const identity = Identity.fromJson(this._data.identity);
this._identity = identity;
return identity;
if (this._data.identity) {
this._identity = Identity.fromJson(this._data.identity);
return this._identity;
}
this._identity = null;
return null;
}
@@ -155,7 +191,7 @@ export class ServiceObject implements ServiceModelInterface {
get auxiliary(): Record<string, any> {
return this._data.auxiliary ?? {};
}
set auxiliary(value: Record<string, any>) {
this._data.auxiliary = value;
}