owltide/utils/client-entity.ts
Hornwitser e3ff872b5c
All checks were successful
/ build (push) Successful in 1m30s
/ deploy (push) Successful in 16s
Refactor ClientSchedule to mutable types
Use a single mutable location, event, slot, etc, for each unique
resource that keeps track of the local editable client copy and
the server copy of the data contained in it.

This makes it much simpler to update these data structures as I can take
advantage of the v-model bindings in Vue.js and work with the system
instead of against it.
2025-06-24 00:07:18 +02:00

82 lines
2.1 KiB
TypeScript

import type { Entity, EntityLiving, Id } from "~/shared/types/common";
import { DateTime, Zone } from "~/shared/utils/luxon";
export abstract class ClientEntity {
/**
Millisecond offset used to indicate this is a new entitity.
*/
static newEntityMillis = -1;
/**
Timestamp of the entity received from server. If this is
a new entity this will have a millisecond offset equal to
{@link ClientEntity.newEntityMillis}.
*/
serverUpdatedAt: DateTime;
/**
True if the server has deleted this entity, but the client
is holding on to it in order to resolve an edit conflcit
*/
serverDeleted: boolean;
constructor(
/**
Server supplied id of this entity. Each kind of entity has its own namespace of ids.
*/
public readonly id: Id,
/**
Server's timestamp of this entity at the time it was modified. If the entity
is unmodified this will track {@link serverUpdatedAt}. If this is a new entity
it'll have a millesecond offset equal to {@link ClientEntity.newEntityMillis}.
*/
public updatedAt: DateTime,
/**
Flag indicating the client intends to delete this entity.
*/
public deleted: boolean,
) {
this.serverUpdatedAt = updatedAt;
this.serverDeleted = deleted;
}
/**
True if this entity does not yet exist on the server.
*/
isNew() {
return this.serverUpdatedAt.toMillis() === ClientEntity.newEntityMillis;
}
/**
True if both the server and the client have modified this entity
independently of each other.
*/
isConflict() {
return this.serverUpdatedAt.toMillis() !== this.updatedAt.toMillis();
}
/**
True if this entity has been modified on the client.
*/
isModified() {
return (
this.isNew()
|| this.deleted
|| this.serverDeleted
);
}
/**
Discard any client side modifications to this entity. Not allowed if
{@link serverDeleted} is true or this is a new entity.
*/
abstract discard(): void
/**
Apply an update delivered from the API to this entity.
*/
abstract apiUpdate(api: EntityLiving, opts: { zone: Zone, locale: string }): void
/**
Serialise this entity to the API format. Not allowed if {@link deleted} is true.
*/
abstract toApi(): Entity
}