@azure/web-pubsub-chat-client 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ ## [1.0.0-beta.1] - 2026-06-09
4
+
5
+ - Initial beta release of `@azure/web-pubsub-chat-client`, the client SDK for Azure Web PubSub Chat.
package/README.md ADDED
@@ -0,0 +1,175 @@
1
+ # Azure Web PubSub Chat Client SDK
2
+
3
+ A client SDK for building chat applications with Azure Web PubSub.
4
+
5
+ > ⚠️ **Internal Preview**: This package is currently for internal use only and is not ready for production.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @azure/web-pubsub-chat-client
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ For a complete example, see [examples/quickstart](./examples/quickstart).
16
+
17
+ ```javascript
18
+ import { ChatClient } from '@azure/web-pubsub-chat-client';
19
+
20
+ // Get client access URL from your server
21
+ const url = await fetch('/negotiate?userId=alice').then(r => r.json()).then(d => d.url);
22
+
23
+ // Start directly with a client access URL...
24
+ const client = await ChatClient.start(url);
25
+
26
+ // ...or with a credential (a callback that returns a client access URL):
27
+ // const client = await ChatClient.start({ getClientAccessUrl: async () => url });
28
+
29
+ console.log(`Started as: ${client.userId}`);
30
+
31
+ // Listen for events
32
+ client.on('message', (event) => {
33
+ const msg = event.message;
34
+ console.log(`${msg.createdBy}: ${msg.content.text}`);
35
+ });
36
+
37
+ client.on('room-joined', (event) => {
38
+ console.log(`Joined room: ${event.room.title}`);
39
+ });
40
+
41
+ // Create a room and send messages
42
+ const room = await client.createRoom('My Room', ['bob']);
43
+ await client.sendToRoom(room.roomId, 'Hello!');
44
+
45
+ // Get message history (auto-paginating async iterator)
46
+ for await (const msg of client.listRoomMessages(room.roomId)) {
47
+ console.log(`${msg.createdBy}: ${msg.content.text}`);
48
+ }
49
+
50
+ // Manage room members
51
+ await client.addUserToRoom(room.roomId, 'charlie');
52
+ await client.removeUserFromRoom(room.roomId, 'charlie');
53
+
54
+ // Cleanup
55
+ await client.stop();
56
+ ```
57
+
58
+ ## API
59
+
60
+ ### ChatClient
61
+
62
+ #### Constructor
63
+
64
+ ```typescript
65
+ new ChatClient(credential: WebPubSubClientCredential)
66
+ ```
67
+
68
+ `ChatClient` is constructed from a `WebPubSubClientCredential`. It builds and owns the underlying transport: `start()` connects and authenticates, `stop()` disconnects. The instance is constructed but not started — call `start()`, or use the static `ChatClient.start(...)` factory below (which also accepts a plain client-access URL) to construct-and-start in one step.
69
+
70
+ #### Static Methods
71
+
72
+ | Method | Description |
73
+ |--------|-------------|
74
+ | `ChatClient.start(clientAccessUrl, options?)` | Construct from a client-access URL and start (`options?: StartOptions`) |
75
+ | `ChatClient.start(credential, options?)` | Construct from a `WebPubSubClientCredential` and start (`options?: StartOptions`) |
76
+
77
+ #### Properties
78
+
79
+ | Property | Type | Description |
80
+ |----------|------|-------------|
81
+ | `userId` | `string` | Current user's ID (throws if not started). Read-only — set internally on `start()`. |
82
+ | `rooms` | `RoomInfo[]` | Snapshot of currently joined rooms (not live-updated) |
83
+
84
+ #### Methods
85
+
86
+ | Method | Description |
87
+ |--------|-------------|
88
+ | `start(options?)` | Connect and authenticate. Idempotent; concurrent calls share one in-flight promise. After `stop()` the client can be started again. Accepts `{ abortSignal }`. |
89
+ | `stop()` | Disconnect and reset client state. Returns `Promise<void>`. |
90
+ | `createRoom(title, members, options?)` | Create a new room with initial members. The current user is automatically added to the members list. Options: `{ roomId?, abortSignal? }` — supply `roomId` to choose an explicit id, otherwise the service assigns one. |
91
+ | `getRoomDetail(roomId, options?)` | Get the detailed view of a room (`RoomDetail`). Options: `{ withMembers?, abortSignal? }` — pass `withMembers: true` to populate the `members` list (omitted otherwise). |
92
+ | `addUserToRoom(roomId, userId, options?)` | Add user to room (admin operation) |
93
+ | `removeUserFromRoom(roomId, userId, options?)` | Remove user from room (admin operation) |
94
+ | `sendToRoom(roomId, message, options?)` | Send text message to room, returns a `SendMessageResult` (`{ messageId }`) |
95
+ | `listRoomMessages(roomId, options?)` | Paged async iterator over room message history (auto-paginates). Use `for await` to stream every message, or `.byPage({ maxPageSize })` to load up to `maxPageSize` messages at a time. `options = { startId?, endId?, maxPageSize?, abortSignal? }` |
96
+ | `getUserProfile(userId, options?)` | Get user profile |
97
+
98
+ Every asynchronous method accepts an optional final `options` argument
99
+ extending `OperationOptions` (`{ abortSignal?: AbortSignalLike }`) to
100
+ cancel in-flight invocations:
101
+
102
+ ```ts
103
+ const ac = new AbortController();
104
+ setTimeout(() => ac.abort(), 5000);
105
+ await client.sendToRoom(roomId, "hi", { abortSignal: ac.signal });
106
+ ```
107
+
108
+ #### Errors
109
+
110
+ Operations reject with a `ChatError` (extends `Error`) carrying a
111
+ service-defined `code`. Known codes are exposed as `KnownChatErrorCode`;
112
+ the service may return additional codes in newer versions, so always
113
+ handle the unknown-code case.
114
+
115
+ ```ts
116
+ import { ChatError, KnownChatErrorCode } from "@azure/web-pubsub-chat-client";
117
+
118
+ try {
119
+ await client.sendToRoom(roomId, "hi");
120
+ } catch (err) {
121
+ if (err instanceof ChatError && err.code === KnownChatErrorCode.UnknownRoom) {
122
+ // re-join or refresh local state
123
+ } else {
124
+ throw err;
125
+ }
126
+ }
127
+ ```
128
+
129
+ | Code | Meaning |
130
+ |------|---------|
131
+ | `KnownChatErrorCode.RoomAlreadyExists` | Tried to create a room whose `roomId` is already in use. |
132
+ | `KnownChatErrorCode.UserAlreadyInRoom` | Adding a user that is already a member. |
133
+ | `KnownChatErrorCode.NoPermissionInRoom` | Caller lacks permission to perform the operation. |
134
+ | `KnownChatErrorCode.NotStarted` | An API was called before `start()` resolved. |
135
+ | `KnownChatErrorCode.UnknownRoom` | The room is not in the client's local cache (joined or created). |
136
+ | `KnownChatErrorCode.InvalidServerResponse` | The service returned a malformed response. |
137
+
138
+ #### Event Listeners
139
+
140
+ Chat events use the same shape as the underlying `WebPubSubClient`:
141
+ one `on(event, listener)` overload per event, returning `void`, paired
142
+ with `off(event, listener)` for removal. Pass the same callback
143
+ reference to `off()` to unregister.
144
+
145
+ ```ts
146
+ const onMsg = (event) => {
147
+ console.log(event.message.content.text);
148
+ };
149
+ client.on('message', onMsg);
150
+ // later
151
+ client.off('message', onMsg);
152
+ ```
153
+
154
+ | Event name | Listener argument | Description |
155
+ |------------|-------------------|-------------|
156
+ | `started` | `OnStartedArgs` | `start()` completed successfully — `userId` and `rooms` are populated. |
157
+ | `stopped` | `OnStoppedArgs` | The client transitioned to not-started (explicit `stop()` or transport-driven). |
158
+ | `message` | `OnMessageArgs` | New message received (or sent by this client). |
159
+ | `room-joined` | `OnRoomJoinedArgs` | This client joined a room. |
160
+ | `room-left` | `OnRoomLeftArgs` | This client left a room. |
161
+ | `member-joined` | `OnMemberJoinedArgs` | Another user joined a room this client is in. |
162
+ | `member-left` | `OnMemberLeftArgs` | Another user left a room this client is in. |
163
+
164
+ The underlying connection is managed internally and is not exposed. Use the
165
+ chat-level `started` / `stopped` events for lifecycle notifications;
166
+ lower-level connection events (`connected`, `disconnected`) are not
167
+ currently surfaced.
168
+
169
+ ## Examples
170
+
171
+ See the [examples](./examples) directory for complete working examples.
172
+
173
+ ## License
174
+
175
+ MIT