Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update type declarations in ably.d.ts for LiveObjects #1967

Merged
merged 2 commits into from
Feb 13, 2025
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
274 changes: 274 additions & 0 deletions ably.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1566,6 +1566,25 @@ export type ErrorCallback = (error: ErrorInfo | null) => void;
*/
export type LiveObjectUpdateCallback<T> = (update: T) => void;

/**
* The callback used for the events emitted by {@link LiveObjects}.
*/
export type LiveObjectsEventCallback = () => void;

/**
* The callback used for the lifecycle events emitted by {@link LiveObject}.
*/
export type LiveObjectLifecycleEventCallback = () => void;

/**
* A function passed to {@link LiveObjects.batch} to group multiple Live Object operations into a single channel message.
*
* Must not be `async`.
*
* @param batchContext - A {@link BatchContext} object that allows grouping operations on Live Objects for this batch.
*/
export type BatchCallback = (batchContext: BatchContext) => void;

// Internal Interfaces

// To allow a uniform (callback) interface between on and once even in the
Expand Down Expand Up @@ -2032,6 +2051,40 @@ export declare interface PushChannel {
listSubscriptions(params?: Record<string, string>): Promise<PaginatedResult<PushChannelSubscription>>;
}

/**
* The `LiveObjectsEvents` namespace describes the possible values of the {@link LiveObjectsEvent} type.
*/
declare namespace LiveObjectsEvents {
/**
* The local Live Objects state is currently being synchronized with the Ably service.
*/
type SYNCING = 'syncing';
/**
* The local Live Objects state has been synchronized with the Ably service.
*/
type SYNCED = 'synced';
}

/**
* Describes the events emitted by a {@link LiveObjects} object.
*/
export type LiveObjectsEvent = LiveObjectsEvents.SYNCED | LiveObjectsEvents.SYNCING;

/**
* The `LiveObjectLifecycleEvents` namespace describes the possible values of the {@link LiveObjectLifecycleEvent} type.
*/
declare namespace LiveObjectLifecycleEvents {
/**
* Indicates that the object has been deleted from the Live Objects pool and should no longer be interacted with.
*/
type DELETED = 'deleted';
}

/**
* Describes the events emitted by a {@link LiveObject} object.
*/
export type LiveObjectLifecycleEvent = LiveObjectLifecycleEvents.DELETED;

/**
* Enables the LiveObjects state to be subscribed to for a channel.
*/
Expand Down Expand Up @@ -2062,6 +2115,59 @@ export declare interface LiveObjects {
* @returns A promise which, upon success, will be fulfilled with a {@link LiveMap} object. Upon failure, the promise will be rejected with an {@link ErrorInfo} object which explains the error.
*/
getRoot<T extends LiveMapType = DefaultRoot>(): Promise<LiveMap<T>>;

/**
* Creates a new {@link LiveMap} object instance with the provided entries.
*
* @param entries - The initial entries for the new {@link LiveMap} object.
* @returns A promise which, upon success, will be fulfilled with a {@link LiveMap} object. Upon failure, the promise will be rejected with an {@link ErrorInfo} object which explains the error.
*/
createMap<T extends LiveMapType>(entries?: T): Promise<LiveMap<T>>;

/**
* Creates a new {@link LiveCounter} object instance with the provided `count` value.
*
* @param count - The initial value for the new {@link LiveCounter} object.
* @returns A promise which, upon success, will be fulfilled with a {@link LiveCounter} object. Upon failure, the promise will be rejected with an {@link ErrorInfo} object which explains the error.
*/
createCounter(count?: number): Promise<LiveCounter>;

/**
* Allows you to group multiple operations together and send them to the Ably service in a single channel message.
* As a result, other clients will receive the changes as a single channel message after the batch function has completed.
*
* This method accepts a synchronous callback, which is provided with a {@link BatchContext} object.
* Use the context object to access Live Object instances in your state and batch operations for them.
*
* The objects' data is not modified inside the callback function. Instead, the objects will be updated
* when the batched operations are applied by the Ably service and echoed back to the client.
*
* @param callback - A batch callback function used to group operations together. Cannot be an `async` function.
* @returns A promise which resolves upon success of the operation and rejects with an {@link ErrorInfo} object upon its failure.
*/
batch(callback: BatchCallback): Promise<void>;

/**
* Registers the provided listener for the specified event. If `on()` is called more than once with the same listener and event, the listener is added multiple times to its listener registry. Therefore, as an example, assuming the same listener is registered twice using `on()`, and an event is emitted once, the listener would be invoked twice.
*
* @param event - The named event to listen for.
* @param callback - The event listener.
* @returns A {@link OnLiveObjectsEventResponse} object that allows the provided listener to be deregistered from future updates.
*/
on(event: LiveObjectsEvent, callback: LiveObjectsEventCallback): OnLiveObjectsEventResponse;

/**
* Removes all registrations that match both the specified listener and the specified event.
*
* @param event - The named event.
* @param callback - The event listener.
*/
off(event: LiveObjectsEvent, callback: LiveObjectsEventCallback): void;

/**
* Deregisters all registrations, for all events and listeners.
*/
offAll(): void;
}

declare global {
Expand Down Expand Up @@ -2095,6 +2201,97 @@ export type DefaultRoot =
? LiveObjectsTypes['root'] // "root" property exists, and it is of an expected type, we can use this interface for the root object in LiveObjects.
: `Provided type definition for the "root" object in LiveObjectsTypes is not of an expected LiveMapType`;

/**
* Object returned from an `on` call, allowing the listener provided in that call to be deregistered.
*/
export declare interface OnLiveObjectsEventResponse {
/**
* Deregisters the listener passed to the `on` call.
*/
off(): void;
}

/**
* Enables grouping multiple Live Object operations together by providing `BatchContext*` wrapper objects.
*/
export declare interface BatchContext {
/**
* Mirrors the {@link LiveObjects.getRoot} method and returns a {@link BatchContextLiveMap} wrapper for the root object on a channel.
*
* @returns A {@link BatchContextLiveMap} object.
*/
getRoot<T extends LiveMapType = DefaultRoot>(): BatchContextLiveMap<T>;
}

/**
* A wrapper around the {@link LiveMap} object that enables batching operations inside a {@link BatchCallback}.
*/
export declare interface BatchContextLiveMap<T extends LiveMapType> {
/**
* Mirrors the {@link LiveMap.get} method and returns the value associated with a key in the map.
*
* @param key - The key to retrieve the value for.
* @returns A {@link LiveObject}, a primitive type (string, number, boolean, or binary data) or `undefined` if the key doesn't exist in a map or the associated {@link LiveObject} has been deleted. Always `undefined` if this map object is deleted.
*/
get<TKey extends keyof T & string>(key: TKey): T[TKey] | undefined;

/**
* Returns the number of key/value pairs in the map.
*/
size(): number;

/**
* Similar to the {@link LiveMap.set} method, but instead, it adds an operation to set a key in the map with the provided value to the current batch, to be sent in a single message to the Ably service.
*
* This does not modify the underlying data of this object. Instead, the change is applied when
* the published operation is echoed back to the client and applied to the object.
* To get notified when object gets updated, use the {@link LiveObject.subscribe} method.
*
* @param key - The key to set the value for.
* @param value - The value to assign to the key.
*/
set<TKey extends keyof T & string>(key: TKey, value: T[TKey]): void;

/**
* Similar to the {@link LiveMap.remove} method, but instead, it adds an operation to remove a key from the map to the current batch, to be sent in a single message to the Ably service.
*
* This does not modify the underlying data of this object. Instead, the change is applied when
* the published operation is echoed back to the client and applied to the object.
* To get notified when object gets updated, use the {@link LiveObject.subscribe} method.
*
* @param key - The key to set the value for.
*/
remove<TKey extends keyof T & string>(key: TKey): void;
}

/**
* A wrapper around the {@link LiveCounter} object that enables batching operations inside a {@link BatchCallback}.
*/
export declare interface BatchContextLiveCounter {
/**
* Returns the current value of the counter.
*/
value(): number;

/**
* Similar to the {@link LiveCounter.increment} method, but instead, it adds an operation to increment the counter value to the current batch, to be sent in a single message to the Ably service.
*
* This does not modify the underlying data of this object. Instead, the change is applied when
* the published operation is echoed back to the client and applied to the object.
* To get notified when object gets updated, use the {@link LiveObject.subscribe} method.
*
* @param amount - The amount by which to increase the counter value.
*/
increment(amount: number): void;

/**
* An alias for calling {@link BatchContextLiveCounter.increment | BatchContextLiveCounter.increment(-amount)}
*
* @param amount - The amount by which to decrease the counter value.
*/
decrement(amount: number): void;
}

/**
* The `LiveMap` class represents a key/value map data structure, similar to a JavaScript Map, where all changes are synchronized across clients in realtime.
* Conflict-free resolution for updates follows Last Write Wins (LWW) semantics, meaning that if two clients update the same key in the map, the update with the most recent timestamp wins.
Expand All @@ -2116,6 +2313,31 @@ export declare interface LiveMap<T extends LiveMapType> extends LiveObject<LiveM
* Returns the number of key/value pairs in the map.
*/
size(): number;

/**
* Sends an operation to the Ably system to set a key on this `LiveMap` object to a specified value.
*
* This does not modify the underlying data of this object. Instead, the change is applied when
* the published operation is echoed back to the client and applied to the object.
* To get notified when object gets updated, use the {@link LiveObject.subscribe} method.
*
* @param key - The key to set the value for.
* @param value - The value to assign to the key.
* @returns A promise which resolves upon success of the operation and rejects with an {@link ErrorInfo} object upon its failure.
*/
set<TKey extends keyof T & string>(key: TKey, value: T[TKey]): Promise<void>;

/**
* Sends an operation to the Ably system to remove a key from this `LiveMap` object.
*
* This does not modify the underlying data of this object. Instead, the change is applied when
* the published operation is echoed back to the client and applied to the object.
* To get notified when object gets updated, use the {@link LiveObject.subscribe} method.
*
* @param key - The key to remove.
* @returns A promise which resolves upon success of the operation and rejects with an {@link ErrorInfo} object upon its failure.
*/
remove<TKey extends keyof T & string>(key: TKey): Promise<void>;
}

/**
Expand Down Expand Up @@ -2145,6 +2367,26 @@ export declare interface LiveCounter extends LiveObject<LiveCounterUpdate> {
* Returns the current value of the counter.
*/
value(): number;

/**
* Sends an operation to the Ably system to increment the value of this `LiveCounter` object.
*
* This does not modify the underlying data of this object. Instead, the change is applied when
* the published operation is echoed back to the client and applied to the object.
* To get notified when object gets updated, use the {@link LiveObject.subscribe} method.
*
* @param amount - The amount by which to increase the counter value.
* @returns A promise which resolves upon success of the operation and rejects with an {@link ErrorInfo} object upon its failure.
*/
increment(amount: number): Promise<void>;

/**
* An alias for calling {@link LiveCounter.increment | LiveCounter.increment(-amount)}
*
* @param amount - The amount by which to decrease the counter value.
* @returns A promise which resolves upon success of the operation and rejects with an {@link ErrorInfo} object upon its failure.
*/
decrement(amount: number): Promise<void>;
}

/**
Expand Down Expand Up @@ -2185,6 +2427,28 @@ export declare interface LiveObject<TUpdate extends LiveObjectUpdate = LiveObjec
* Deregisters all listeners from updates for this Live Object.
*/
unsubscribeAll(): void;

/**
* Registers the provided listener for the specified event. If `on()` is called more than once with the same listener and event, the listener is added multiple times to its listener registry. Therefore, as an example, assuming the same listener is registered twice using `on()`, and an event is emitted once, the listener would be invoked twice.
*
* @param event - The named event to listen for.
* @param callback - The event listener.
* @returns A {@link OnLiveObjectLifecycleEventResponse} object that allows the provided listener to be deregistered from future updates.
*/
on(event: LiveObjectLifecycleEvent, callback: LiveObjectLifecycleEventCallback): OnLiveObjectLifecycleEventResponse;

/**
* Removes all registrations that match both the specified listener and the specified event.
*
* @param event - The named event.
* @param callback - The event listener.
*/
off(event: LiveObjectLifecycleEvent, callback: LiveObjectLifecycleEventCallback): void;

/**
* Deregisters all registrations, for all events and listeners.
*/
offAll(): void;
}

/**
Expand All @@ -2207,6 +2471,16 @@ export declare interface SubscribeResponse {
unsubscribe(): void;
}

/**
* Object returned from an `on` call, allowing the listener provided in that call to be deregistered.
*/
export declare interface OnLiveObjectLifecycleEventResponse {
/**
* Deregisters the listener passed to the `on` call.
*/
off(): void;
}

/**
* Enables messages to be published and historic messages to be retrieved for a channel.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/liveobjects/livecounter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export class LiveCounter extends LiveObject<LiveCounterData, LiveCounterUpdate>
}

/**
* Alias for calling {@link LiveCounter.increment | LiveCounter.increment(-amount)}
* An alias for calling {@link LiveCounter.increment | LiveCounter.increment(-amount)}
*/
async decrement(amount: number): Promise<void> {
this._liveObjects.throwIfMissingStatePublishMode();
Expand Down
14 changes: 6 additions & 8 deletions src/plugins/liveobjects/liveobjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,10 @@ export class LiveObjects {
/**
* Send a MAP_CREATE operation to the realtime system to create a new map object in the pool.
*
* Locally on the client it creates a zero-value object with the corresponding id and returns it.
* The object initialization with the initial value is expected to happen when the corresponding MAP_CREATE operation is echoed
* back to the client and applied to the object following the regular operation application procedure.
* Once the ACK message is received, the method returns the object from the local pool if it got created due to
* the echoed MAP_CREATE operation, or if it wasn't received yet, the method creates a new object locally using the provided data and returns it.
*
* @returns A promise which resolves upon receiving the ACK message for the published operation message. A promise is resolved with a zero-value object created in the local pool.
* @returns A promise which resolves upon receiving the ACK message for the published operation message. A promise is resolved with an object containing provided data.
*/
async createMap<T extends API.LiveMapType>(entries?: T): Promise<LiveMap<T>> {
this.throwIfMissingStatePublishMode();
Expand Down Expand Up @@ -134,11 +133,10 @@ export class LiveObjects {
/**
* Send a COUNTER_CREATE operation to the realtime system to create a new counter object in the pool.
*
* Locally on the client it creates a zero-value object with the corresponding id and returns it.
* The object initialization with the initial value is expected to happen when the corresponding COUNTER_CREATE operation is echoed
* back to the client and applied to the object following the regular operation application procedure.
* Once the ACK message is received, the method returns the object from the local pool if it got created due to
* the echoed COUNTER_CREATE operation, or if it wasn't received yet, the method creates a new object locally using the provided data and returns it.
*
* @returns A promise which resolves upon receiving the ACK message for the published operation message. A promise is resolved with a zero-value object created in the local pool.
* @returns A promise which resolves upon receiving the ACK message for the published operation message. A promise is resolved with an object containing provided data.
*/
async createCounter(count?: number): Promise<LiveCounter> {
this.throwIfMissingStatePublishMode();
Expand Down
Loading