diff --git a/src/plugins/liveobjects/livemap.ts b/src/plugins/liveobjects/livemap.ts index b147dcf80..ec30576df 100644 --- a/src/plugins/liveobjects/livemap.ts +++ b/src/plugins/liveobjects/livemap.ts @@ -1,24 +1,27 @@ import { LiveObject, LiveObjectData } from './liveobject'; -import { StateValue } from './statemessage'; +import { LiveObjects } from './liveobjects'; +import { MapSemantics, StateValue } from './statemessage'; export interface ObjectIdStateData { - /** - * A reference to another state object, used to support composable state objects. - */ + /** A reference to another state object, used to support composable state objects. */ objectId: string; } export interface ValueStateData { /** - * A concrete leaf value in the state object graph. + * The encoding the client should use to interpret the value. + * Analogous to the `encoding` field on the `Message` and `PresenceMessage` types. */ + encoding?: string; + /** A concrete leaf value in the state object graph. */ value: StateValue; } export type StateData = ObjectIdStateData | ValueStateData; export interface MapEntry { - // TODO: add tombstone, timeserial + tombstone: boolean; + timeserial: string; data: StateData; } @@ -27,6 +30,15 @@ export interface LiveMapData extends LiveObjectData { } export class LiveMap extends LiveObject { + constructor( + liveObjects: LiveObjects, + private _semantics: MapSemantics, + initialData?: LiveMapData | null, + objectId?: string, + ) { + super(liveObjects, initialData, objectId); + } + /** * Returns the value associated with the specified key in the underlying Map object. * If no element is associated with the specified key, undefined is returned. diff --git a/src/plugins/liveobjects/liveobjects.ts b/src/plugins/liveobjects/liveobjects.ts index 9e4373e42..f83cc91b3 100644 --- a/src/plugins/liveobjects/liveobjects.ts +++ b/src/plugins/liveobjects/liveobjects.ts @@ -155,17 +155,19 @@ export class LiveObjects { } let newObject: LiveObject; - switch (entry.objectType) { + // assign to a variable so TS doesn't complain about 'never' type in the default case + const objectType = entry.objectType; + switch (objectType) { case 'LiveCounter': newObject = new LiveCounter(this, entry.objectData, objectId); break; case 'LiveMap': - newObject = new LiveMap(this, entry.objectData, objectId); + newObject = new LiveMap(this, entry.semantics, entry.objectData, objectId); break; default: - throw new this._client.ErrorInfo(`Unknown live object type: ${entry.objectType}`, 40000, 400); + throw new this._client.ErrorInfo(`Unknown live object type: ${objectType}`, 40000, 400); } newObject.setRegionalTimeserial(entry.regionalTimeserial); diff --git a/src/plugins/liveobjects/liveobjectspool.ts b/src/plugins/liveobjects/liveobjectspool.ts index 5f46c1a0a..c19433cae 100644 --- a/src/plugins/liveobjects/liveobjectspool.ts +++ b/src/plugins/liveobjects/liveobjectspool.ts @@ -2,6 +2,7 @@ import type BaseClient from 'common/lib/client/baseclient'; import { LiveMap } from './livemap'; import { LiveObject } from './liveobject'; import { LiveObjects } from './liveobjects'; +import { MapSemantics } from './statemessage'; export const ROOT_OBJECT_ID = 'root'; @@ -41,7 +42,7 @@ export class LiveObjectsPool { private _getInitialPool(): Map { const pool = new Map(); - const root = new LiveMap(this._liveObjects, null, ROOT_OBJECT_ID); + const root = new LiveMap(this._liveObjects, MapSemantics.LWW, null, ROOT_OBJECT_ID); pool.set(root.getObjectId(), root); return pool; } diff --git a/src/plugins/liveobjects/syncliveobjectsdatapool.ts b/src/plugins/liveobjects/syncliveobjectsdatapool.ts index 1d30c5ad6..3c787eb09 100644 --- a/src/plugins/liveobjects/syncliveobjectsdatapool.ts +++ b/src/plugins/liveobjects/syncliveobjectsdatapool.ts @@ -1,5 +1,6 @@ import { LiveObjectData } from './liveobject'; import { LiveObjects } from './liveobjects'; +import { MapSemantics } from './statemessage'; export interface LiveObjectDataEntry { objectData: LiveObjectData; @@ -7,14 +8,26 @@ export interface LiveObjectDataEntry { objectType: 'LiveMap' | 'LiveCounter'; } +export interface LiveCounterDataEntry extends LiveObjectDataEntry { + created: boolean; + objectType: 'LiveCounter'; +} + +export interface LiveMapDataEntry extends LiveObjectDataEntry { + objectType: 'LiveMap'; + semantics: MapSemantics; +} + +export type AnyDataEntry = LiveCounterDataEntry | LiveMapDataEntry; + /** * @internal */ export class SyncLiveObjectsDataPool { - private _pool: Map; + private _pool: Map; constructor(private _liveObjects: LiveObjects) { - this._pool = new Map(); + this._pool = new Map(); } entries() { @@ -30,6 +43,6 @@ export class SyncLiveObjectsDataPool { } reset(): void { - this._pool = new Map(); + this._pool = new Map(); } }