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

[SDK-3916] Update publishing methods to accept a Message-shaped object #1515

Merged
merged 2 commits into from
Nov 29, 2023
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
75 changes: 40 additions & 35 deletions ably.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2055,28 +2055,28 @@
*/
presence: Presence;
/**
* Retrieves a {@link Types.PaginatedResult} object, containing an array of historical {@link Message} objects for the channel. If the channel is configured to persist messages, then messages can be retrieved from history for up to 72 hours in the past. If not, messages can only be retrieved from history for up to two minutes in the past.
* Retrieves a {@link Types.PaginatedResult} object, containing an array of historical {@link InboundMessage} objects for the channel. If the channel is configured to persist messages, then messages can be retrieved from history for up to 72 hours in the past. If not, messages can only be retrieved from history for up to two minutes in the past.
*
* @param params - A set of parameters which are used to specify which messages should be retrieved.
* @returns A promise which, upon success, will be fulfilled with a {@link Types.PaginatedResult} object containing an array of {@link Message} objects. Upon failure, the promise will be rejected with an {@link ErrorInfo} object which explains the error.
* @returns A promise which, upon success, will be fulfilled with a {@link Types.PaginatedResult} object containing an array of {@link InboundMessage} objects. Upon failure, the promise will be rejected with an {@link ErrorInfo} object which explains the error.
*/
history(params?: RestHistoryParams): Promise<PaginatedResult<Message>>;
history(params?: RestHistoryParams): Promise<PaginatedResult<InboundMessage>>;
/**
* Publishes an array of messages to the channel.
*
* @param messages - An array of {@link Message} objects.
* @param options - Optional parameters, such as [`quickAck`](https://faqs.ably.com/why-are-some-rest-publishes-on-a-channel-slow-and-then-typically-faster-on-subsequent-publishes) sent as part of the query string.
* @returns A promise which resolves upon success of the operation and rejects with an {@link ErrorInfo} object upon its failure.
*/
publish(messages: any[], options?: PublishOptions): Promise<void>;
publish(messages: Message[], options?: PublishOptions): Promise<void>;
/**
* Publishes a message to the channel.
*
* @param message - A {@link Message} object.
* @param options - Optional parameters, such as [`quickAck`](https://faqs.ably.com/why-are-some-rest-publishes-on-a-channel-slow-and-then-typically-faster-on-subsequent-publishes) sent as part of the query string.
* @returns A promise which resolves upon success of the operation and rejects with an {@link ErrorInfo} object upon its failure.
*/
publish(message: any, options?: PublishOptions): Promise<void>;
publish(message: Message, options?: PublishOptions): Promise<void>;
/**
* Publishes a single message to the channel with the given event name and payload.
*
Expand Down Expand Up @@ -2124,14 +2124,14 @@
* @param event - The event name.
* @param listener - An event listener function.
*/
unsubscribe(event: string, listener: messageCallback<Message>): void;
unsubscribe(event: string, listener: messageCallback<InboundMessage>): void;
/**
* Deregisters the given listener from all event names in the array.
*
* @param events - An array of event names.
* @param listener - An event listener function.
*/
unsubscribe(events: Array<string>, listener: messageCallback<Message>): void;
unsubscribe(events: Array<string>, listener: messageCallback<InboundMessage>): void;
/**
* Deregisters all listeners for the given event name.
*
Expand All @@ -2150,13 +2150,13 @@
* @param filter - A {@link MessageFilter}.
* @param listener - An event listener function.
*/
unsubscribe(filter: MessageFilter, listener?: messageCallback<Message>): void;
unsubscribe(filter: MessageFilter, listener?: messageCallback<InboundMessage>): void;
/**
* Deregisters the given listener (for any/all event names). This removes an earlier subscription.
*
* @param listener - An event listener function.
*/
unsubscribe(listener: messageCallback<Message>): void;
unsubscribe(listener: messageCallback<InboundMessage>): void;
/**
* Deregisters all listeners to messages on this channel. This removes all earlier subscriptions.
*/
Expand All @@ -2179,12 +2179,12 @@
*/
detach(): Promise<void>;
/**
* Retrieves a {@link Types.PaginatedResult} object, containing an array of historical {@link Message} objects for the channel. If the channel is configured to persist messages, then messages can be retrieved from history for up to 72 hours in the past. If not, messages can only be retrieved from history for up to two minutes in the past.
* Retrieves a {@link Types.PaginatedResult} object, containing an array of historical {@link InboundMessage} objects for the channel. If the channel is configured to persist messages, then messages can be retrieved from history for up to 72 hours in the past. If not, messages can only be retrieved from history for up to two minutes in the past.
*
* @param params - A set of parameters which are used to specify which presence members should be retrieved.
* @returns A promise which, upon success, will be fulfilled with a {@link Types.PaginatedResult} object containing an array of {@link Message} objects. Upon failure, the promise will be rejected with an {@link ErrorInfo} object which explains the error.
* @returns A promise which, upon success, will be fulfilled with a {@link Types.PaginatedResult} object containing an array of {@link InboundMessage} objects. Upon failure, the promise will be rejected with an {@link ErrorInfo} object which explains the error.
*/
history(params?: RealtimeHistoryParams): Promise<PaginatedResult<Message>>;
history(params?: RealtimeHistoryParams): Promise<PaginatedResult<InboundMessage>>;
/**
* Sets the {@link ChannelOptions} for the channel.
*
Expand All @@ -2199,15 +2199,15 @@
* @param listener - An event listener function.
* @returns A promise which, upon successful attachment to the channel, will be fulfilled with a {@link ChannelStateChange} object. If the channel was already attached the promise will be resolved with `null`. Upon failure, the promise will be rejected with an {@link ErrorInfo} object.
*/
subscribe(event: string, listener?: messageCallback<Message>): Promise<ChannelStateChange | null>;
subscribe(event: string, listener?: messageCallback<InboundMessage>): Promise<ChannelStateChange | null>;
/**
* Registers a listener for messages on this channel for multiple event name values.
*
* @param events - An array of event names.
* @param listener - An event listener function.
* @returns A promise which, upon successful attachment to the channel, will be fulfilled with a {@link ChannelStateChange} object. If the channel was already attached the promise will be resolved with `null`. Upon failure, the promise will be rejected with an {@link ErrorInfo} object.
*/
subscribe(events: Array<string>, listener?: messageCallback<Message>): Promise<ChannelStateChange | null>;
subscribe(events: Array<string>, listener?: messageCallback<InboundMessage>): Promise<ChannelStateChange | null>;
/**
* {@label WITH_MESSAGE_FILTER}
*
Expand All @@ -2217,14 +2217,14 @@
* @param listener - An event listener function.
* @returns A promise which, upon successful attachment to the channel, will be fulfilled with a {@link ChannelStateChange} object. If the channel was already attached the promise will be resolved with `null`. Upon failure, the promise will be rejected with an {@link ErrorInfo} object.
*/
subscribe(filter: MessageFilter, listener?: messageCallback<Message>): Promise<ChannelStateChange | null>;
subscribe(filter: MessageFilter, listener?: messageCallback<InboundMessage>): Promise<ChannelStateChange | null>;
/**
* Registers a listener for messages on this channel. The caller supplies a listener function, which is called each time one or more messages arrives on the channel.
*
* @param callback - An event listener function.
* @returns A promise which, upon successful attachment to the channel, will be fulfilled with a {@link ChannelStateChange} object. If the channel was already attached the promise will be resolved with `null`. Upon failure, the promise will be rejected with an {@link ErrorInfo} object.
*/
subscribe(callback: messageCallback<Message>): Promise<ChannelStateChange | null>;
subscribe(callback: messageCallback<InboundMessage>): Promise<ChannelStateChange | null>;
/**
* Publishes a single message to the channel with the given event name and payload. When publish is called with this client library, it won't attempt to implicitly attach to the channel, so long as [transient publishing](https://ably.com/docs/realtime/channels#transient-publish) is available in the library. Otherwise, the client will implicitly attach.
*
Expand All @@ -2239,14 +2239,14 @@
* @param messages - An array of {@link Message} objects.
* @returns A promise which resolves upon success of the operation and rejects with an {@link ErrorInfo} object upon its failure.
*/
publish(messages: any[]): Promise<void>;
publish(messages: Message[]): Promise<void>;
/**
* Publish a message to the channel. When publish is called with this client library, it won't attempt to implicitly attach to the channel.
*
* @param message - A {@link Message} object.
* @returns A promise which resolves upon success of the operation and rejects with an {@link ErrorInfo} object upon its failure.
*/
publish(message: any): Promise<void>;
publish(message: Message): Promise<void>;
/**
* Returns a promise which is resolved when the channel reaches the specified {@link ChannelState}. If the channel is already in the specified state, the promise is resolved immediately.
*
Expand Down Expand Up @@ -2304,8 +2304,8 @@
*/
get(name: string, channelOptions?: ChannelOptions): T;
/**
* @experimental This is a preview feature and may change in a future non-major release.

Check warning on line 2307 in ably.d.ts

View workflow job for this annotation

GitHub Actions / lint

Invalid JSDoc tag name "experimental"
* This experimental method allows you to create custom realtime data feeds by selectively subscribing

Check warning on line 2308 in ably.d.ts

View workflow job for this annotation

GitHub Actions / lint

Expected no lines between tags
* to receive only part of the data from the channel.
* See the [announcement post](https://pages.ably.com/subscription-filters-preview) for more information.
*
Expand All @@ -2329,61 +2329,66 @@
/**
* Contains an individual message that is sent to, or received from, Ably.
*/
class Message {
interface Message {
/**
* The client ID of the publisher of this message.
*/
clientId: string;
clientId?: string;
/**
* The connection ID of the publisher of this message.
*/
connectionId?: string;
/**
* The message payload, if provided.
*/
data: any;
data?: any;
/**
* This is typically empty, as all messages received from Ably are automatically decoded client-side using this value. However, if the message encoding cannot be processed, this attribute contains the remaining transformations not applied to the `data` payload.
*/
encoding: string;
encoding?: string;
/**
* A JSON object of arbitrary key-value pairs that may contain metadata, and/or ancillary payloads. Valid payloads include `push`, `delta`, `ref` and `headers`.
*/
extras: any;
extras?: any;
/**
* Unique ID assigned by Ably to this message.
*/
id: string;
id?: string;
/**
* The event name.
*/
name: string;
name?: string;
/**
* Timestamp of when the message was received by Ably, as milliseconds since the Unix epoch.
*/
timestamp: number;
timestamp?: number;
}

/**
* A message received from Ably.
*/
type InboundMessage = Message & Required<Pick<Message, 'id' | 'timestamp'>>;

/**
* Static utilities related to messages.
*/
interface MessageStatic {
/**
* A static factory method to create a `Message` object from a deserialized Message-like object encoded using Ably's wire protocol.
* A static factory method to create an `InboundMessage` object from a deserialized InboundMessage-like object encoded using Ably's wire protocol.
*
* @param JsonObject - A `Message`-like deserialized object.
* @param JsonObject - A `InboundMessage`-like deserialized object.
* @param channelOptions - A {@link ChannelOptions} object. If you have an encrypted channel, use this to allow the library to decrypt the data.
* @returns A promise which will be fulfilled with a `Message` object.
* @returns A promise which will be fulfilled with an `InboundMessage` object.
*/
fromEncoded: (JsonObject: any, channelOptions?: ChannelOptions) => Promise<Message>;
fromEncoded: (JsonObject: any, channelOptions?: ChannelOptions) => Promise<InboundMessage>;
/**
* A static factory method to create an array of `Message` objects from an array of deserialized Message-like object encoded using Ably's wire protocol.
* A static factory method to create an array of `InboundMessage` objects from an array of deserialized InboundMessage-like object encoded using Ably's wire protocol.
*
* @param JsonArray - An array of `Message`-like deserialized objects.
* @param JsonArray - An array of `InboundMessage`-like deserialized objects.
* @param channelOptions - A {@link ChannelOptions} object. If you have an encrypted channel, use this to allow the library to decrypt the data.
* @returns A promise which will be fulfilled with an array of {@link Message} objects.
* @returns A promise which will be fulfilled with an array of {@link InboundMessage} objects.
*/
fromEncodedArray: (JsonArray: any[], channelOptions?: ChannelOptions) => Promise<Message[]>;
fromEncodedArray: (JsonArray: any[], channelOptions?: ChannelOptions) => Promise<InboundMessage[]>;
}

/**
Expand Down Expand Up @@ -2601,7 +2606,7 @@
*/
class PaginatedResult<T> {
/**
* Contains the current page of results; for example, an array of {@link Message} or {@link PresenceMessage} objects for a channel history request.
* Contains the current page of results; for example, an array of {@link InboundMessage} or {@link PresenceMessage} objects for a channel history request.
*/
items: T[];
/**
Expand Down
17 changes: 12 additions & 5 deletions test/package/browser/template/src/index-default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,19 @@ globalThis.testAblyPackage = async function () {
const channel = realtime.channels.get('channel');
await attachChannel(channel);

const receivedMessagePromise = new Promise<void>((resolve) => {
channel.subscribe(() => {
resolve();
});
const receivedMessagePromise = new Promise<Types.InboundMessage>((resolve) => {
channel.subscribe(resolve);
});

// Check that we can use the TypeScript overload that accepts name and data as separate arguments
await channel.publish('message', { foo: 'bar' });
await receivedMessagePromise;
const receivedMessage = await receivedMessagePromise;

// Check that id and timestamp of a message received from Ably can be assigned to non-optional types
const { id: string, timestamp: number } = receivedMessage;

channel.unsubscribe();

// Check that we can use the TypeScript overload that accepts a Message object
await channel.publish({ name: 'message', data: { foo: 'bar' } });
};
18 changes: 13 additions & 5 deletions test/package/browser/template/src/index-modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,21 @@ globalThis.testAblyPackage = async function () {
const channel = realtime.channels.get('channel');
await attachChannel(channel);

const receivedMessagePromise = new Promise<void>((resolve) => {
channel.subscribe(() => {
resolve();
});
const receivedMessagePromise = new Promise<Types.InboundMessage>((resolve) => {
channel.subscribe(resolve);
});

// Check that we can use the TypeScript overload that accepts name and data as separate arguments
await channel.publish('message', { foo: 'bar' });
await receivedMessagePromise;
const receivedMessage = await receivedMessagePromise;

// Check that id and timestamp of a message received from Ably can be assigned to non-optional types
const { id: string, timestamp: number } = receivedMessage;

await checkStandaloneFunction();

channel.unsubscribe();

// Check that we can use the TypeScript overload that accepts a Message object
await channel.publish({ name: 'message', data: { foo: 'bar' } });
};
Loading