Skip to content

Commit 9741076

Browse files
committed
Expose protocol v6 typed fields on public ObjectOperation and ObjectData
The public ObjectOperation interface is updated to use the protocol v6 field names (mapCreate, mapSet, mapRemove, counterCreate, counterInc). The previous fields (mapOp, counterOp, map, counter) are preserved as deprecated aliases. The public ObjectData interface previously exposed a combined `value` field, which was an incorrect internal representation leaking through the public API (introduced in 54f8ae2). The LODR-042 [1] DR proposed that subscription events should be equivalent to the REST API publish endpoint syntax. With protocol v6 aligning the realtime protocol and REST API in LODR-51 [2], ObjectData now exposes the same typed fields available on the wire: boolean, bytes, number, string, json - with decoded values (bytes as Buffer/ArrayBuffer, json as parsed objects). The combined `value` field is preserved as a deprecated alias. Both new and deprecated fields are populated for backwards compatibility; deprecated fields will be removed in a future major version. [1] https://ably.atlassian.net/wiki/spaces/LOB/pages/4235722804/LODR-042+LiveObjects+Realtime+Client+API+Improvements#Subscriptions [2] https://ably.atlassian.net/wiki/x/AQAPEgE
1 parent be7ea17 commit 9741076

4 files changed

Lines changed: 259 additions & 49 deletions

File tree

liveobjects.d.ts

Lines changed: 110 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1577,18 +1577,61 @@ export interface ObjectOperation {
15771577
action: ObjectOperationAction;
15781578
/** The ID of the object the operation was applied to. */
15791579
objectId: string;
1580-
/** The payload for the operation if it is a mutation operation on a map object. */
1580+
1581+
/**
1582+
* The payload for the operation if the action is {@link ObjectOperationActions.MAP_CREATE}.
1583+
* Defines the initial value of the map object.
1584+
*/
1585+
mapCreate?: MapCreate;
1586+
/**
1587+
* The payload for the operation if the action is {@link ObjectOperationActions.MAP_SET}.
1588+
* Describes the key and value to set on the map object.
1589+
*/
1590+
mapSet?: MapSet;
1591+
/**
1592+
* The payload for the operation if the action is {@link ObjectOperationActions.MAP_REMOVE}.
1593+
* Describes the key to remove from the map object.
1594+
*/
1595+
mapRemove?: MapRemove;
1596+
/**
1597+
* The payload for the operation if the action is {@link ObjectOperationActions.COUNTER_CREATE}.
1598+
* Defines the initial value of the counter object.
1599+
*/
1600+
counterCreate?: CounterCreate;
1601+
/**
1602+
* The payload for the operation if the action is {@link ObjectOperationActions.COUNTER_INC}.
1603+
* Describes the value to add to the counter.
1604+
*/
1605+
counterInc?: CounterInc;
1606+
/**
1607+
* The payload for the operation if the action is {@link ObjectOperationActions.OBJECT_DELETE}.
1608+
*/
1609+
objectDelete?: ObjectDelete;
1610+
1611+
/**
1612+
* The payload for the operation if it is a mutation operation on a map object.
1613+
*
1614+
* @deprecated This property is deprecated and will be removed in a future major version. Use {@link mapSet} and {@link mapRemove} instead.
1615+
*/
15811616
mapOp?: ObjectsMapOp;
1582-
/** The payload for the operation if it is a mutation operation on a counter object. */
1617+
/**
1618+
* The payload for the operation if it is a mutation operation on a counter object.
1619+
*
1620+
* @deprecated This property is deprecated and will be removed in a future major version. Use {@link counterInc} instead.
1621+
*/
15831622
counterOp?: ObjectsCounterOp;
15841623
/**
15851624
* The payload for the operation if the action is {@link ObjectOperationActions.MAP_CREATE}.
15861625
* Defines the initial value of the map object.
1626+
*
1627+
* @deprecated This property is deprecated and will be removed in a future major version. Use {@link mapCreate} instead.
15871628
*/
15881629
map?: ObjectsMap;
15891630
/**
15901631
* The payload for the operation if the action is {@link ObjectOperationActions.COUNTER_CREATE}.
15911632
* Defines the initial value of the counter object.
1633+
*
1634+
* @deprecated This property is deprecated and will be removed in a future major version. Use {@link counterCreate} instead.
15921635
*/
15931636
counter?: ObjectsCounter;
15941637
}
@@ -1643,13 +1686,77 @@ export interface ObjectsCounter {
16431686
count?: number;
16441687
}
16451688

1689+
/**
1690+
* Describes the payload for a MAP_CREATE operation.
1691+
*/
1692+
export interface MapCreate {
1693+
/** The conflict-resolution semantics used by the map object, one of the {@link ObjectsMapSemantics} enum values. */
1694+
semantics: ObjectsMapSemantics;
1695+
/** The map entries, indexed by key. */
1696+
entries: Record<string, ObjectsMapEntry>;
1697+
}
1698+
1699+
/**
1700+
* Describes the payload for a MAP_SET operation on a map object.
1701+
*/
1702+
export interface MapSet {
1703+
/** The key to set. */
1704+
key: string;
1705+
/** The value to set. */
1706+
value: ObjectData;
1707+
}
1708+
1709+
/**
1710+
* Describes the payload for a MAP_REMOVE operation on a map object.
1711+
*/
1712+
export interface MapRemove {
1713+
/** The key to remove. */
1714+
key: string;
1715+
}
1716+
1717+
/**
1718+
* Describes the payload for a COUNTER_CREATE operation.
1719+
*/
1720+
export interface CounterCreate {
1721+
/** The initial counter value. */
1722+
count: number;
1723+
}
1724+
1725+
/**
1726+
* Describes the payload for a COUNTER_INC operation on a counter object.
1727+
*/
1728+
export interface CounterInc {
1729+
/** The value to be added to the counter. */
1730+
number: number;
1731+
}
1732+
1733+
/**
1734+
* Describes the payload for an OBJECT_DELETE operation.
1735+
*/
1736+
export interface ObjectDelete {}
1737+
16461738
/**
16471739
* Represents a value in an object on a channel.
16481740
*/
16491741
export interface ObjectData {
16501742
/** A reference to another object. */
16511743
objectId?: string;
1652-
/** A decoded primitive value. */
1744+
/** A boolean leaf value in the object. */
1745+
boolean?: boolean;
1746+
/** A decoded binary leaf value in the object. */
1747+
bytes?: Buffer | ArrayBuffer;
1748+
/** A number leaf value in the object. */
1749+
number?: number;
1750+
/** A string leaf value in the object. */
1751+
string?: string;
1752+
/** A decoded JSON leaf value in the object. */
1753+
json?: JsonObject | JsonArray;
1754+
1755+
/**
1756+
* A decoded primitive value.
1757+
*
1758+
* @deprecated This property is deprecated and will be removed in a future major version. Use one of the typed {@link boolean}, {@link bytes}, {@link number}, {@link string} or {@link json} fields instead.
1759+
*/
16531760
value?: Primitive;
16541761
}
16551762

src/plugins/liveobjects/objectmessage.ts

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,8 @@ function toUserFacingObjectData(data: ObjectData): ObjectsApi.ObjectData {
443443
}
444444

445445
return {
446+
...data,
447+
// deprecated field for backwards compatibility
446448
value: getObjectDataPrimitive(data),
447449
};
448450
}
@@ -455,40 +457,56 @@ function toUserFacingMapEntry(entry: ObjectsMapEntry<ObjectData>): ObjectsApi.Ob
455457
}
456458

457459
function toUserFacingObjectOperation(operation: ObjectOperation<ObjectData>): ObjectsApi.ObjectOperation {
458-
// Convert internal field names to user-facing API field names
459-
let map: ObjectsApi.ObjectsMap | undefined;
460-
if (operation.mapCreate) {
461-
map = {
462-
...operation.mapCreate,
463-
semantics: mapSemantics[operation.mapCreate.semantics] || 'unknown',
460+
const { mapCreate: internalMapCreate, mapSet: internalMapSet, mapRemove, counterCreate, counterInc } = operation;
461+
462+
let mapCreate: ObjectsApi.MapCreate | undefined;
463+
if (internalMapCreate) {
464+
mapCreate = {
465+
...internalMapCreate,
466+
semantics: mapSemantics[internalMapCreate.semantics] ?? 'unknown',
464467
entries: Object.fromEntries(
465-
Object.entries(operation.mapCreate.entries).map(([key, entry]) => [key, toUserFacingMapEntry(entry)]),
468+
Object.entries(internalMapCreate.entries).map(([key, entry]) => [key, toUserFacingMapEntry(entry)]),
466469
),
467470
};
468471
}
469472

473+
let mapSet: ObjectsApi.MapSet | undefined;
474+
if (internalMapSet) {
475+
mapSet = {
476+
...internalMapSet,
477+
value: toUserFacingObjectData(internalMapSet.value),
478+
};
479+
}
480+
481+
// ObjectOperation deprecated fields for backwards compatibility
470482
let mapOp: ObjectsApi.ObjectsMapOp | undefined;
471-
if (operation.mapSet) {
483+
if (mapSet) {
472484
mapOp = {
473-
key: operation.mapSet.key,
474-
data: toUserFacingObjectData(operation.mapSet.value),
485+
key: mapSet.key,
486+
data: mapSet.value,
475487
};
476-
} else if (operation.mapRemove) {
477-
mapOp = { key: operation.mapRemove.key };
488+
} else if (mapRemove) {
489+
mapOp = { key: mapRemove.key };
478490
}
479491

480492
let counterOp: ObjectsApi.ObjectsCounterOp | undefined;
481-
if (operation.counterInc) {
482-
counterOp = { amount: operation.counterInc.number };
493+
if (counterInc) {
494+
counterOp = { amount: counterInc.number };
483495
}
484496

485497
return {
498+
...operation,
486499
action: operationActions[operation.action] || 'unknown',
487-
objectId: operation.objectId,
500+
mapCreate,
501+
mapSet,
502+
mapRemove,
503+
counterCreate,
504+
counterInc,
505+
// deprecated fields
488506
mapOp,
489507
counterOp,
490-
map,
491-
counter: operation.counterCreate,
508+
map: mapCreate,
509+
counter: counterCreate,
492510
};
493511
}
494512

test/common/modules/private_api_recorder.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ define(['test/support/output_directory_paths'], function (outputDirectoryPaths)
2222
'call.ObjectMessage.encode',
2323
'call.ObjectMessage.fromValues',
2424
'call.ObjectMessage.getMessageSize',
25+
'call.ObjectMessage.toUserFacingMessage',
2526
'call.Platform.Config.push.storage.clear',
2627
'call.Platform.nextTick',
2728
'call.PresenceMessage.fromValues',

0 commit comments

Comments
 (0)