Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,004 changes: 106 additions & 1,898 deletions ably.d.ts

Large diffs are not rendered by default.

1,853 changes: 1,830 additions & 23 deletions objects.d.ts

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/plugins/objects/batchcontext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {
Instance,
Primitive,
Value,
} from '../../../ably';
} from '../../../objects';
import { DefaultInstance } from './instance';
import { LiveCounter } from './livecounter';
import { LiveMap } from './livemap';
Expand Down
5 changes: 2 additions & 3 deletions src/plugins/objects/instance.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import type BaseClient from 'common/lib/client/baseclient';
import type { EventCallback, Subscription } from '../../../ably';
import type {
AnyInstance,
BatchContext,
BatchFunction,
CompactedJsonValue,
CompactedValue,
EventCallback,
Instance,
InstanceSubscriptionEvent,
LiveObject as LiveObjectType,
Primitive,
Subscription,
Value,
} from '../../../ably';
} from '../../../objects';
import { LiveCounter } from './livecounter';
import { LiveMap } from './livemap';
import { LiveObject } from './liveobject';
Expand Down
6 changes: 5 additions & 1 deletion src/plugins/objects/livecounter.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { __livetype } from '../../../ably';
import { LiveCounter as PublicLiveCounter } from '../../../objects';
import { LiveObject, LiveObjectData, LiveObjectUpdate, LiveObjectUpdateNoop } from './liveobject';
import { ObjectData, ObjectMessage, ObjectOperation, ObjectOperationAction, ObjectsCounterOp } from './objectmessage';
import { RealtimeObject } from './realtimeobject';
Expand All @@ -12,7 +14,9 @@ export interface LiveCounterUpdate extends LiveObjectUpdate {
}

/** @spec RTLC1, RTLC2 */
export class LiveCounter extends LiveObject<LiveCounterData, LiveCounterUpdate> {
export class LiveCounter extends LiveObject<LiveCounterData, LiveCounterUpdate> implements PublicLiveCounter {
declare readonly [__livetype]: 'LiveCounter'; // type-only, unique symbol to satisfy branded interfaces, no JS emitted

/**
* Returns a {@link LiveCounter} instance with a 0 value.
*
Expand Down
9 changes: 5 additions & 4 deletions src/plugins/objects/livecountervaluetype.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type * as API from '../../../ably';
import { __livetype } from '../../../ably';
import { LiveCounter } from '../../../objects';
import { ObjectId } from './objectid';
import {
createInitialValueJSONString,
Expand All @@ -17,8 +18,8 @@ import { RealtimeObject } from './realtimeobject';
* Properties of this class are immutable after construction and the instance
* will be frozen to prevent mutation.
*/
export class LiveCounterValueType implements API.LiveCounter {
declare readonly [API.__livetype]: 'LiveCounter'; // type-only, unique symbol to satisfy branded interfaces, no JS emitted
export class LiveCounterValueType implements LiveCounter {
declare readonly [__livetype]: 'LiveCounter'; // type-only, unique symbol to satisfy branded interfaces, no JS emitted
private readonly _livetype = 'LiveCounter'; // use a runtime property to provide a reliable cross-bundle type identification instead of `instanceof` operator
private readonly _count: number;

Expand All @@ -27,7 +28,7 @@ export class LiveCounterValueType implements API.LiveCounter {
Object.freeze(this);
}

static create(initialCount: number = 0): API.LiveCounter {
static create(initialCount: number = 0): LiveCounter {
// We can't directly import the ErrorInfo class from the core library into the plugin (as this would bloat the plugin size),
// and, since we're in a user-facing static method, we can't expect a user to pass a client library instance, as this would make the API ugly.
// Since we can't use ErrorInfo here, we won't do any validation at this step; instead, validation will happen in the mutation methods
Expand Down
34 changes: 21 additions & 13 deletions src/plugins/objects/livemap.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { dequal } from 'dequal';
import { __livetype } from '../../../ably';

import type * as API from '../../../ably';
import {
CompactedJsonValue,
CompactedValue,
LiveMap as PublicLiveMap,
LiveObject as PublicLiveObject,
Primitive,
Value,
} from '../../../objects';
import { LiveCounter } from './livecounter';
import { LiveCounterValueType } from './livecountervaluetype';
import { LiveMapValueType } from './livemapvaluetype';
Expand All @@ -23,7 +31,7 @@ export interface ObjectIdObjectData {

export interface ValueObjectData {
/** A decoded leaf value from {@link WireObjectData}. */
value: API.Primitive;
value: Primitive;
}

export type LiveMapObjectData = ObjectIdObjectData | ValueObjectData;
Expand All @@ -39,17 +47,17 @@ export interface LiveMapData extends LiveObjectData {
data: Map<string, LiveMapEntry>; // RTLM3
}

export interface LiveMapUpdate<T extends Record<string, API.Value>> extends LiveObjectUpdate {
export interface LiveMapUpdate<T extends Record<string, Value>> extends LiveObjectUpdate {
update: { [keyName in keyof T & string]?: 'updated' | 'removed' };
_type: 'LiveMapUpdate';
}

/** @spec RTLM1, RTLM2 */
export class LiveMap<T extends Record<string, API.Value> = Record<string, API.Value>>
export class LiveMap<T extends Record<string, Value> = Record<string, Value>>
extends LiveObject<LiveMapData, LiveMapUpdate<T>>
implements API.LiveMap<T>
implements PublicLiveMap<T>
{
declare readonly [API.__livetype]: 'LiveMap'; // type-only, unique symbol to satisfy branded interfaces, no JS emitted
declare readonly [__livetype]: 'LiveMap'; // type-only, unique symbol to satisfy branded interfaces, no JS emitted

constructor(
realtimeObject: RealtimeObject,
Expand Down Expand Up @@ -88,7 +96,7 @@ export class LiveMap<T extends Record<string, API.Value> = Record<string, API.Va
realtimeObject: RealtimeObject,
objectId: string,
key: string,
value: API.Value,
value: Value,
): Promise<ObjectMessage[]> {
const client = realtimeObject.getClient();

Expand All @@ -113,7 +121,7 @@ export class LiveMap<T extends Record<string, API.Value> = Record<string, API.Va
const typedObjectData: ObjectIdObjectData = { objectId: mapCreateMsg.operation?.objectId! };
objectData = typedObjectData;
} else {
const typedObjectData: ValueObjectData = { value: value as API.Primitive };
const typedObjectData: ValueObjectData = { value: value as Primitive };
objectData = typedObjectData;
}

Expand Down Expand Up @@ -163,7 +171,7 @@ export class LiveMap<T extends Record<string, API.Value> = Record<string, API.Va
/**
* @internal
*/
static validateKeyValue(realtimeObject: RealtimeObject, key: string, value: API.Value): void {
static validateKeyValue(realtimeObject: RealtimeObject, key: string, value: Value): void {
const client = realtimeObject.getClient();

if (typeof key !== 'string') {
Expand Down Expand Up @@ -498,7 +506,7 @@ export class LiveMap<T extends Record<string, API.Value> = Record<string, API.Va
*
* @internal
*/
compact(visitedObjects?: Map<string, Record<string, any>>): API.CompactedValue<API.LiveMap<T>> {
compact(visitedObjects?: Map<string, Record<string, any>>): CompactedValue<PublicLiveMap<T>> {
const visited = visitedObjects ?? new Map<string, Record<string, any>>();
const result: Record<keyof T, any> = {} as Record<keyof T, any>;

Expand Down Expand Up @@ -540,7 +548,7 @@ export class LiveMap<T extends Record<string, API.Value> = Record<string, API.Va
*
* @internal
*/
compactJson(visitedObjectIds?: Set<string>): API.CompactedJsonValue<API.LiveMap<T>> {
compactJson(visitedObjectIds?: Set<string>): CompactedJsonValue<PublicLiveMap<T>> {
const visited = visitedObjectIds ?? new Set<string>();
const result: Record<keyof T, any> = {} as Record<keyof T, any>;

Expand Down Expand Up @@ -954,7 +962,7 @@ export class LiveMap<T extends Record<string, API.Value> = Record<string, API.Va
/**
* Returns value as is if object data stores a primitive type, or a reference to another LiveObject from the pool if it stores an objectId.
*/
private _getResolvedValueFromObjectData(data: LiveMapObjectData): API.Value | undefined {
private _getResolvedValueFromObjectData(data: LiveMapObjectData): Value | undefined {
// if object data stores primitive value, just return it as is.
const primitiveValue = (data as ValueObjectData).value;
if (primitiveValue != null) {
Expand All @@ -973,7 +981,7 @@ export class LiveMap<T extends Record<string, API.Value> = Record<string, API.Va
return undefined;
}

return refObject as unknown as API.LiveObject; // RTLM5d2f2
return refObject as unknown as PublicLiveObject; // RTLM5d2f2
}

private _isMapEntryTombstoned(entry: LiveMapEntry): boolean {
Expand Down
17 changes: 8 additions & 9 deletions src/plugins/objects/livemapvaluetype.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type * as API from '../../../ably';
import { __livetype } from '../../../ably';
import { LiveMap as PublicLiveMap, Primitive, Value } from '../../../objects';
import { LiveCounterValueType } from './livecountervaluetype';
import { LiveMap, LiveMapObjectData, ObjectIdObjectData, ValueObjectData } from './livemap';
import { ObjectId } from './objectid';
Expand Down Expand Up @@ -30,10 +31,8 @@ import { RealtimeObject } from './realtimeobject';
* 4. This behavior should be documented and it's the user's responsibility to understand
* how they mutate their data when working with value type classes
*/
export class LiveMapValueType<T extends Record<string, API.Value> = Record<string, API.Value>>
implements API.LiveMap<T>
{
declare readonly [API.__livetype]: 'LiveMap'; // type-only, unique symbol to satisfy branded interfaces, no JS emitted
export class LiveMapValueType<T extends Record<string, Value> = Record<string, Value>> implements PublicLiveMap<T> {
declare readonly [__livetype]: 'LiveMap'; // type-only, unique symbol to satisfy branded interfaces, no JS emitted
private readonly _livetype = 'LiveMap'; // use a runtime property to provide a reliable cross-bundle type identification instead of `instanceof` operator
private readonly _entries: T | undefined;

Expand All @@ -42,9 +41,9 @@ export class LiveMapValueType<T extends Record<string, API.Value> = Record<strin
Object.freeze(this);
}

static create<T extends Record<string, API.Value>>(
static create<T extends Record<string, Value>>(
initialEntries?: T,
): API.LiveMap<T extends Record<string, API.Value> ? T : {}> {
): PublicLiveMap<T extends Record<string, Value> ? T : {}> {
// We can't directly import the ErrorInfo class from the core library into the plugin (as this would bloat the plugin size),
// and, since we're in a user-facing static method, we can't expect a user to pass a client library instance, as this would make the API ugly.
// Since we can't use ErrorInfo here, we won't do any validation at this step; instead, validation will happen in the mutation methods
Expand Down Expand Up @@ -114,7 +113,7 @@ export class LiveMapValueType<T extends Record<string, API.Value> = Record<strin

private static async _createInitialValueOperation(
realtimeObject: RealtimeObject,
entries?: Record<string, API.Value>,
entries?: Record<string, Value>,
): Promise<{
initialValueOperation: Pick<ObjectOperation<ObjectData>, 'map'>;
nestedObjectsCreateMsgs: ObjectMessage[];
Expand All @@ -138,7 +137,7 @@ export class LiveMapValueType<T extends Record<string, API.Value> = Record<strin
objectData = typedObjectData;
} else {
// Handle primitive values
const typedObjectData: ValueObjectData = { value: value as API.Primitive };
const typedObjectData: ValueObjectData = { value: value as Primitive };
objectData = typedObjectData;
}

Expand Down
15 changes: 7 additions & 8 deletions src/plugins/objects/objectmessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ import type BaseClient from 'common/lib/client/baseclient';
import type RealtimeChannel from 'common/lib/client/realtimechannel';
import type { MessageEncoding } from 'common/lib/types/basemessage';
import type * as Utils from 'common/lib/util/utils';
import type * as API from '../../../ably';
import type { JsonArray, JsonObject } from '../../../ably';
import type * as ObjectsApi from '../../../objects';

const operationActions: API.ObjectOperationAction[] = [
const operationActions: ObjectsApi.ObjectOperationAction[] = [
'map.create',
'map.set',
'map.remove',
Expand All @@ -14,7 +13,7 @@ const operationActions: API.ObjectOperationAction[] = [
'object.delete',
];

const mapSemantics: API.ObjectsMapSemantics[] = ['lww'];
const mapSemantics: ObjectsApi.ObjectsMapSemantics[] = ['lww'];

export type EncodeObjectDataFunction = (data: ObjectData | WireObjectData) => WireObjectData;

Expand All @@ -41,7 +40,7 @@ export interface ObjectData {
/** A reference to another object, used to support composable object structures. */
objectId?: string; // OD2a
/** A decoded leaf value from {@link WireObjectData}. */
value?: API.Primitive;
value?: ObjectsApi.Primitive;
}

/**
Expand Down Expand Up @@ -337,7 +336,7 @@ function copyMsg(
return result;
}

function stringifyOperation(operation: ObjectOperation<ObjectData>): API.ObjectOperation {
function stringifyOperation(operation: ObjectOperation<ObjectData>): ObjectsApi.ObjectOperation {
return {
...operation,
action: operationActions[operation.action] || 'unknown',
Expand Down Expand Up @@ -444,7 +443,7 @@ export class ObjectMessage {
return this.object != null;
}

toUserFacingMessage(channel: RealtimeChannel): API.ObjectMessage {
toUserFacingMessage(channel: RealtimeChannel): ObjectsApi.ObjectMessage {
return {
id: this.id!,
clientId: this.clientId,
Expand Down Expand Up @@ -789,7 +788,7 @@ export class WireObjectMessage {
client.Platform.BufferUtils.base64Decode(String(objectData.bytes));
}

let decodedJson: JsonObject | JsonArray | undefined;
let decodedJson: ObjectsApi.JsonObject | ObjectsApi.JsonArray | undefined;
if (objectData.json != null) {
decodedJson = JSON.parse(objectData.json); // OD5a2, OD5b3
}
Expand Down
5 changes: 2 additions & 3 deletions src/plugins/objects/pathobject.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import type BaseClient from 'common/lib/client/baseclient';
import type { EventCallback, Subscription } from '../../../ably';
import type {
AnyPathObject,
BatchContext,
BatchFunction,
CompactedJsonValue,
CompactedValue,
EventCallback,
Instance,
LiveObject as LiveObjectType,
PathObject,
PathObjectSubscriptionEvent,
PathObjectSubscriptionOptions,
Primitive,
Subscription,
Value,
} from '../../../ably';
} from '../../../objects';
import { DefaultInstance } from './instance';
import { LiveCounter } from './livecounter';
import { LiveMap } from './livemap';
Expand Down
8 changes: 2 additions & 6 deletions src/plugins/objects/pathobjectsubscriptionregister.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import type BaseClient from 'common/lib/client/baseclient';
import type {
EventCallback,
PathObjectSubscriptionEvent,
PathObjectSubscriptionOptions,
Subscription,
} from '../../../ably';
import type { EventCallback, Subscription } from '../../../ably';
import type { PathObjectSubscriptionEvent, PathObjectSubscriptionOptions } from '../../../objects';
import { ObjectMessage } from './objectmessage';
import { DefaultPathObject } from './pathobject';
import { RealtimeObject } from './realtimeobject';
Expand Down
9 changes: 5 additions & 4 deletions src/plugins/objects/realtimeobject.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type BaseClient from 'common/lib/client/baseclient';
import type RealtimeChannel from 'common/lib/client/realtimechannel';
import type EventEmitter from 'common/lib/util/eventemitter';
import type * as API from '../../../ably';
import type { ChannelState } from '../../../ably';
import type * as ObjectsApi from '../../../objects';
import { DEFAULTS } from './defaults';
import { LiveCounter } from './livecounter';
import { LiveMap } from './livemap';
Expand Down Expand Up @@ -79,7 +80,7 @@ export class RealtimeObject {
* A user can provide an explicit type for the this method to explicitly set the type structure on this particular channel.
* This is useful when working with multiple channels with different underlying data structure.
*/
async get<T extends Record<string, API.Value>>(): Promise<API.PathObject<API.LiveMap<T>>> {
async get<T extends Record<string, ObjectsApi.Value>>(): Promise<ObjectsApi.PathObject<ObjectsApi.LiveMap<T>>> {
this._throwIfMissingChannelMode('object_subscribe');

// implicit attach before proceeding
Expand Down Expand Up @@ -223,7 +224,7 @@ export class RealtimeObject {
/**
* @internal
*/
actOnChannelState(state: API.ChannelState, hasObjects?: boolean): void {
actOnChannelState(state: ChannelState, hasObjects?: boolean): void {
switch (state) {
case 'attached':
this.onAttached(hasObjects);
Expand Down Expand Up @@ -474,7 +475,7 @@ export class RealtimeObject {
}
}

private _throwIfInChannelState(channelState: API.ChannelState[]): void {
private _throwIfInChannelState(channelState: ChannelState[]): void {
if (channelState.includes(this._channel.state)) {
throw this._client.ErrorInfo.fromValues(this._channel.invalidStateError());
}
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/objects/rootbatchcontext.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Instance, Value } from '../../../ably';
import type { Instance, Value } from '../../../objects';
import { DefaultBatchContext } from './batchcontext';
import { ObjectMessage } from './objectmessage';
import { RealtimeObject } from './realtimeobject';
Expand Down
Loading
Loading