Skip to content

Commit

Permalink
Merge pull request #431 from ably/release/0.3.0
Browse files Browse the repository at this point in the history
chore: 0.3.0 release
  • Loading branch information
AndyTWF authored Jan 6, 2025
2 parents 6d1b04a + 1a957f5 commit bb19b93
Show file tree
Hide file tree
Showing 20 changed files with 210 additions and 59 deletions.
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,37 @@

This contains only the most important and/or user-facing changes; for a full changelog, see the commit history.

## [0.3.0](https://github.com/ably/ably-chat-js/tree/0.3.0) (2025-01-06)

### Breaking Changes

Please see `UPGRADING.md` for full guidance on upgrading from version 0.2.1 and before.

- The default typing timeout has now been reduced to 5 seconds. [#361](https://github.com/ably/ably-chat-js/pull/361)
- Room and Connection status types have been renamed. [#382](https://github.com/ably/ably-chat-js/pull/382)
- Renamed the `timeserial` field on the `Message` type to `serial`. Messages may now be compared for global order by string comparison of this field.
- `Rooms.get` is now asynchronous and returns a `Promise` that will resolve once any `release` operations on the room are complete. [#387](https://github.com/ably/ably-chat-js/pull/387).
- The `Room.channel` property is now an instance of `Ably.RealtimeChannel`, rather than a `Promise`. [#387](https://github.com/ably/ably-chat-js/pull/387)
- In React, accessing the room via `useRoom`, or properties of the room via other hooks, now returns `ValueType | undefined`. Once the room's promise is resolved (see above), this will update to the actual value. [#387](https://github.com/ably/ably-chat-js/pull/387)
- The default Room status is now `Initialized`. The `Initializing` status is retained for use in React when the room has not yet been resolved. [#387](https://github.com/ably/ably-chat-js/pull/387)
- The `direction` argument to message history has been replaced by `orderBy`, which uses a new enum `OrderBy` with values `OldestFirst` and `NewestFirst`. Its behavior is identical to `direction: forwards | backwards`.

### New Features

- Added new fields to Messages to support editing and deleting. [#362](https://github.com/ably/ably-chat-js/pull/362)
- Added the ability to delete messages in the chat. [#365](https://github.com/ably/ably-chat-js/pull/365)
- Added the ability to edit messages in the chat. [#378](https://github.com/ably/ably-chat-js/pull/378)

### Fixed Bugs

- The Room will now transition immediately to `released` if `release` is called whilst its status is `Initialized`. [#400](https://github.com/ably/ably-chat-js/pull/400)
- When paginating messages (e.g. via `getPreviousMessages`) the objects returned by successive pages will now fully implement the `Message` interface. Previously they were simple JSON objects after the first page. [#403](https://github.com/ably/ably-chat-js/pull/403).
- Fixed a bug whereby a room may get stuck in the `Suspended` status after network issues. [#409](https://github.com/ably/ably-chat-js/pull/409)

### Other Changes

- `ably-chat` is no longer a reserved key on Message and Reaction metadata/headers. [#374](https://github.com/ably/ably-chat-js/pull/374)

## [0.2.1](https://github.com/ably/ably-chat-js/tree/0.2.1) (2024-09-18)

- Fixed a bug that can lead to unhandled promise rejections and error logs when a room is released prior to initialization, particularly in React [#352](https://github.com/ably/ably-chat-js/pull/352)
Expand Down
7 changes: 4 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@
- The second number represents a minor release, which lets users know new functionality or features have been added.
- The third number represents a patch release, which represents bug-fixes and may be used when no action should be required from users.
2. The commit should update `package.json` and `package-lock.json`. Running `npm install` after changing `package.json` will update `package-lock.json`.
3. The commit should also update `version.ts` to set the agent headers.
4. Update the `CHANGELOG.md` with any customer-affecting changes since the last release.
5. Update the README.md for any references to the new version.
3. The commit should also update `react-native/package.json` to the appropriate version.
4. The commit should also update `version.ts` to set the agent headers.
5. Update the `CHANGELOG.md` with any customer-affecting changes since the last release.
6. Update the README.md for any references to the new version.
3. Merge the commit into main.
4. Tag a release using [Github releases](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository#creating-a-release). The version needs to match the one from the commit. Use the "Generate release notes" button to
add changelog notes and update as required.
Expand Down
32 changes: 11 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
Ably Chat is a set of purpose-built APIs for a host of chat features enabling you to create 1:1, 1:Many, Many:1 and Many:Many chat rooms for any scale. It is designed to meet a wide range of chat use cases, such as livestreams, in-game communication, customer support, or social interactions in SaaS products. Built on [Ably's](https://ably.com/) core service, it abstracts complex details to enable efficient chat architectures.

> [!IMPORTANT]
> This SDK is currently under development. If you are interested in being an early adopter and providing feedback then you can [sign up to the private beta](https://forms.gle/vB2kXhCXrTQpzHLu5) and are welcome to [provide us with feedback](https://forms.gle/mBw9M53NYuCBLFpMA). Coming soon: chat moderation, editing and deleting messages.
> This SDK is currently under development. If you are interested in being an early adopter and providing feedback then you can [sign up to the private beta](https://forms.gle/vB2kXhCXrTQpzHLu5) and are welcome to [provide us with feedback](https://forms.gle/mBw9M53NYuCBLFpMA). Coming soon: chat moderation, simplified granular permissions and message reactions.
Get started using the [📚 documentation](https://ably.com/docs/products/chat) and [🚀check out the live demo](https://ably-livestream-chat-demo.vercel.app/), or [📘 browse the API reference](https://sdk.ably.com/builds/ably/ably-chat-js/main/typedoc/).

Expand Down Expand Up @@ -283,8 +283,7 @@ const message = await room.messages.send({

### Updating messages

To update an existing message, call `update` on the `room.messages` property, with the original message you want to update,
the updated fields, and optional operation details to provide extra context for the update.
To update an existing message, call `update` on the `room.messages` property, with the original message you want to update, the updated fields, and optional operation details to provide extra context for the update.

The optional operation details are:

Expand All @@ -309,15 +308,15 @@ const updatedMessage = await room.messages.update(

A `Message` that was updated will have values for `updatedAt` and `updatedBy`, and `isUpdated()` will return `true`.

Note that if you delete an updated message, it is no longer considered _updated_. Only the last operation takes effect.
Note that if you delete an updated message, it is no longer considered _updated_. Only the latest operation takes effect.

#### Handling updates in realtime

Updated messages received from realtime have the `action` parameter set to `ChatMessageActions.MessageUpdate`, and the event received has the `type` set to `MessageEvents.Updated`. Updated messages are full copies of the message, meaning that all that is needed to keep a state or UI up to date is to replace the old message with the received one.
Updated messages received from the server have the `action` parameter set to `ChatMessageActions.MessageUpdate`, and the event received has the `type` set to `MessageEvents.Updated`. Updated messages are full copies of the message, meaning that all that is needed to keep a state or UI up to date is to replace the old message with the received one.

In rare occasions updates might arrive over realtime out of order. To keep a correct state, compare the `version` lexicographically (string compare). Alternatively, the `Message` interface provides convenience methods to compare two instances of the same base message to determine which version is newer: `versionBefore()`, `versionAfter()`, and `versionEqual()`.
On rare occasions updates might arrive from the server out of order (in terms of the global order in which these events occur). An example of this is when messages are transiting between regions, and latencies between nearby regions is lower than those further away. To deterministically determine whether an update should supersede the current version, simply compare the `version` strings using the standard `<` and `>` operators. Alternatively, the `Message` interface provides convenience methods to compare two instances of the same base message to determine which version is newer: `versionBefore()`, `versionAfter()`, and `versionEqual()`.

The same out-of-order situation can happen between updates received over realtime and HTTP responses. In the situation where two concurrent updates happen, both might be received via realtime before the HTTP response of the first one arrives. Always compare the message `version` to determine which instance of a `Message` is newer.
The same out-of-order situation can happen between updates received over realtime and HTTP responses (e.g. when updating a message). In the situation where two concurrent updates happen, both might be received via realtime before the HTTP response of the first one arrives. Always compare the message `version` to determine which instance of a `Message` is newer.

Example for handling updates:

Expand Down Expand Up @@ -373,22 +372,13 @@ const { unsubscribe } = room.messages.subscribe((msg) => console.log(msg));

#### Handling deletes in realtime

Deletion messages received from realtime have the `action` parameter set to `ChatMessageActions.MessageDelete`, and the event received has the `type` set to `MessageEvents.Deleted`.
Just like `updates`, `deletion` messages are also full copies of the message, meaning that all that is needed to keep a state or UI up to date is to replace the old message with the received one.
Deletion messages received from the server have the `action` parameter set to `ChatMessageActions.MessageDelete`, and the event received has the `type` set to `MessageEvents.Deleted`. Similar to `updates`, `deletion` messages are also full copies of the message, meaning that all that is needed to keep a state or UI up to date is to replace the old message with the received one.

On rare occasions, deletes and updates might arrive over realtime out of order.
That is to say, should two concurrent actions happen in disparate regions, you will likely receive the action processed in the region closest to you first.
When the second action arrives, you will need to determine the order of these actions;
this is done by comparing their respective global orders, determined by the `version` field of the message.
On rare occasions, deletes and updates might arrive over realtime out of order. Again, should two concurrent actions happen in disparate regions, you will likely receive the action processed in the region closest to you first, for example.

To keep a correct state, the `Message` interface provides methods to compare two instances of the same base message to determine which action is newer:`actionBefore()`, `actionAfter()`, and `actionEqual()`.
When the second action arrives, you will need to determine the order of these actions; this is done deterministically by comparing the `version` field of the messages, using the standard `<` and `>` operators. For convenience, the `Message` interface provides methods to compare two instances of the same base message to determine which action is newer:`versionBefore()`, `versionAfter()`, and `versionEqual()`.

The same out-of-order situation can happen between deletions received over realtime and HTTP responses.

In the situation where two concurrent deletes happen, both might be received via realtime before the HTTP response of the first one arrives.

In short, always use `actionAfter()`,
`actionBefore()`, or `actionEqual()` to determine the global ordering of two `Message` actions.
The same out-of-order situation can happen between deletions received over realtime and HTTP responses, whereby both might be received via realtime before the HTTP response of the first one arrives.

Example for handling deletes:

Expand All @@ -400,7 +390,7 @@ room.messages.subscribe((event) => {
case MessageEvents.Deleted: {
const serial = event.message.serial;
const index = messages.findIndex((m) => m.serial === serial);
if (index !== -1 && messages[index].actionBefore(event.message)) {
if (index !== -1 && messages[index].versionBefore(event.message)) {
messages[index] = event.message;
}
break;
Expand Down
103 changes: 103 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Upgrade Guide

This guide provides detailed instructions on how to upgrade between major versions of the Chat SDK.

## <= 0.2.1 to 0.3.0

### Room and Connection Status Types

**Expected Impact: High**

These have been renamed for greater clarity. The key changes are that the `RoomStatus` and `ConnectionStatus` identifiers are now enumerations of the possible statuses, whereas before they were an interface name. Furthermore, the current status is now presented as the property `status`, rather than the property `current`.

| Action | Before | After |
| -------------------------------------------------------- | ---------------------------------------------------- | ------------------------------------------------- |
| Get the “current” status of a room | `room.status.current` | `room.status` |
| Get the “current” error related to the room status | `room.status.error` | `room.error` |
| Subscribe to room status updates | `room.status.onChange` | `room.onStatusChange` |
| Remove all room status subscribers | `room.status.offAll` | `room.offAllStatusChange` |
| Compare the room status to some value | `roomStatus === RoomLifecycle.Attached` | `roomStatus === RoomStatus.Attached` |
| Get the “current” connection status | `chat.connection.status.current` | `chat.connection.status` |
| Get the “current” error related to the connection status | `chat.connection.status.error` | `chat.connection.error` |
| Subscribe to connection status updates | `chat.connection.status.onChange` | `chat.connection.onStatusChange` |
| Remove all connection status subscribers | `chat.connection.status.offAll` | `chat.connection.offAllStatusChange` |
| Compare the connection status to some value | `connectionStatus === ConnectionLifecycle.Connected` | `connectionStatus === ConnectionStatus.Connected` |

### Creating a Room Is Now Asynchronous

**Expected Impact: High**

The `Rooms.get` method is now asynchronous, returning a `Promise` which will resolve when the `Room` object is ready. If a `release` operation is in progress for the room, it shall wait for this
process to complete before resolving.

Before:

```ts
const room = chat.rooms.get('basketball-stream', { typing: { timeoutMs: 500 } });
```

After:

```ts
const room = await chat.rooms.get('basketball-stream', { typing: { timeoutMs: 500 } });
```

As a result, the `channel` property of various features (e.g. `messages.channel`) now returns an `Ably.RealtimeChannel` rather than a `Promise`.

### Default Room Status

**Expected Impact: Medium**

The default status of a newly created room is now `Initialized`. It was previously `Initializing`. `Initializing` is still used in React when the room is not yet resolved.

### Message Timeserial Field Rename

**Expected Impact: Medium**

This field has been renamed, so all occurrences of `message.timeserial` should now be changed to `message.serial`.

If you wish to, messages may now be compared for global ordering by comparing their `serial` strings.

```ts
const message1First = message1.serial < message2.serial;
```

The `before` and `after` methods are still available and will be kept for simplicity and autocomplete convenience.

### History Direction Parameter Removed

**Expected Impact: Medium**

The `direction` argument to message history has been replaced by `orderBy`, which uses a new enum `OrderBy` with values `OldestFirst` and `NewestFirst`. Its behavior is identical to `direction: forwards | backwards`.

Before:

```ts
const historicalMessages = await room.messages.get({ direction: 'backwards', limit: 50 });
```

After:

```ts
const historicalMessages = await room.messages.get({ orderBy: OrderBy.NewestFirst, limit: 50 });
```

### React Hooks Room Property Values

**Expected Impact: Low**

In previous versions of React Hooks, properties of the Room (e.g. `room.messages`) and the room itself were returned as `ValueType`. These are now returned as `ValueType | undefined`.

The value will be updated once the internal call to `Rooms.get()` has resolved.

### Typing Timeout

**Expected Impact: Low**

The default is now 5 seconds.

If you wish to retain the old behavior, change your `RoomOptions` when creating a `Room` as follows:

```ts
const room = await chat.rooms.get('basketball-stream', { typing: { timeoutMs: 500 } });
```
3 changes: 2 additions & 1 deletion cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"Failable",
"livestreams",
"livestream",
"clonedeep"
"clonedeep",
"timeserial"
],
// This will ignore anything that's formatted like a lexicographically ordered timeserial
"ignoreRegExpList": ["/\\d{14}-\\d{3}@.*/"],
Expand Down
12 changes: 6 additions & 6 deletions demo/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
},
"dependencies": {
"@ably/chat": "file:..",
"ably": "ably/ably-js#mutable-messages-with-submodule-test",
"ably": "^2.6.0",
"clsx": "^2.1.1",
"nanoid": "^5.0.9",
"react": "^18.3.1",
Expand Down
Loading

0 comments on commit bb19b93

Please sign in to comment.