mezon-light-sdk 1.0.3 → 1.0.6

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.
Files changed (49) hide show
  1. package/README.md +351 -258
  2. package/dist/index.cjs.js +1 -0
  3. package/dist/index.esm.mjs +1 -0
  4. package/dist/{api.gen.d.ts → src/api.gen.d.ts} +166 -150
  5. package/dist/src/api.gen.d.ts.map +1 -0
  6. package/dist/{client.d.ts → src/client.d.ts} +157 -137
  7. package/dist/src/client.d.ts.map +1 -0
  8. package/dist/{constants.d.ts → src/constants.d.ts} +17 -16
  9. package/dist/src/constants.d.ts.map +1 -0
  10. package/dist/src/google/protobuf/wrappers.d.ts +65 -0
  11. package/dist/src/google/protobuf/wrappers.d.ts.map +1 -0
  12. package/dist/{index.d.ts → src/index.d.ts} +6 -5
  13. package/dist/src/index.d.ts.map +1 -0
  14. package/dist/src/proto/api.d.ts +418 -0
  15. package/dist/src/proto/api.d.ts.map +1 -0
  16. package/dist/src/proto/realtime.d.ts +302 -0
  17. package/dist/src/proto/realtime.d.ts.map +1 -0
  18. package/dist/{session.d.ts → src/session.d.ts} +64 -63
  19. package/dist/src/session.d.ts.map +1 -0
  20. package/dist/{socket.d.ts → src/socket.d.ts} +136 -135
  21. package/dist/src/socket.d.ts.map +1 -0
  22. package/dist/{socket.gen.d.ts → src/socket.gen.d.ts} +137 -136
  23. package/dist/src/socket.gen.d.ts.map +1 -0
  24. package/dist/{types.d.ts → src/types.d.ts} +45 -44
  25. package/dist/src/types.d.ts.map +1 -0
  26. package/dist/{utils.d.ts → src/utils.d.ts} +4 -3
  27. package/dist/src/utils.d.ts.map +1 -0
  28. package/dist/{web_socket_adapter_pb.d.ts → src/web_socket_adapter_pb.d.ts} +70 -69
  29. package/dist/src/web_socket_adapter_pb.d.ts.map +1 -0
  30. package/dist/tsconfig.tsbuildinfo +1 -0
  31. package/package.json +43 -22
  32. package/dist/api.gen.js +0 -149
  33. package/dist/client.js +0 -267
  34. package/dist/constants.js +0 -19
  35. package/dist/google/protobuf/struct.d.ts +0 -201
  36. package/dist/google/protobuf/struct.js +0 -449
  37. package/dist/google/protobuf/wrappers.d.ts +0 -238
  38. package/dist/google/protobuf/wrappers.js +0 -506
  39. package/dist/index.js +0 -20
  40. package/dist/proto/api.d.ts +0 -24188
  41. package/dist/proto/api.js +0 -33287
  42. package/dist/proto/realtime.d.ts +0 -36125
  43. package/dist/proto/realtime.js +0 -13947
  44. package/dist/session.js +0 -92
  45. package/dist/socket.gen.js +0 -327
  46. package/dist/socket.js +0 -249
  47. package/dist/types.js +0 -2
  48. package/dist/utils.js +0 -110
  49. package/dist/web_socket_adapter_pb.js +0 -111
package/README.md CHANGED
@@ -1,259 +1,352 @@
1
- # Mezon Light SDK
2
-
3
- A lightweight SDK for Mezon chat integration, providing simple APIs for authentication, real-time messaging, and direct message management.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install mezon-light-sdk
9
- ```
10
-
11
- ## Features
12
-
13
- - 🔐 Simple authentication with ID tokens
14
- - 💬 Real-time messaging via WebSocket (protobuf-based)
15
- - 📨 Direct message (DM) and group DM support
16
- - 🔄 Automatic session management with token refresh
17
- - 📎 Attachment support for messages
18
- - 🎯 TypeScript-first with full type definitions
19
- - ⚡ Exponential backoff for socket connection reliability
20
-
21
- ## Quick Start
22
-
23
- ### 1. Authenticate with ID Token
24
-
25
- ```typescript
26
- import { LightClient, AuthenticationError } from 'mezon-light-sdk';
27
-
28
- try {
29
- const client = await LightClient.authenticate({
30
- id_token: 'your-id-token',
31
- user_id: 'user-123',
32
- username: 'johndoe',
33
- serverkey: 'your-server-key', // optional, uses DEFAULT_SERVER_KEY
34
- gateway_url: 'https://gw.mezon.ai' // optional, uses MEZON_GW_URL
35
- });
36
-
37
- console.log('Authenticated as:', client.userId);
38
- } catch (error) {
39
- if (error instanceof AuthenticationError) {
40
- console.error('Auth failed:', error.message, error.statusCode);
41
- }
42
- }
43
- ```
44
-
45
- ### 2. Restore Session from Storage
46
-
47
- After login, persist the session data and restore it later:
48
-
49
- ```typescript
50
- import { LightClient, SessionError } from 'mezon-light-sdk';
51
-
52
- // Export session for storage
53
- const sessionData = client.exportSession();
54
- // Returns: { token, refresh_token, api_url, user_id }
55
- localStorage.setItem('mezon_session', JSON.stringify(sessionData));
56
-
57
- // Later: restore from storage
58
- try {
59
- const savedData = JSON.parse(localStorage.getItem('mezon_session')!);
60
- const client = LightClient.initClient(savedData);
61
- } catch (error) {
62
- if (error instanceof SessionError) {
63
- console.error('Session restore failed:', error.message);
64
- }
65
- }
66
- ```
67
-
68
- ### 3. Session Management
69
-
70
- Check and refresh the session before connecting:
71
-
72
- ```typescript
73
- // Check if session token is expired
74
- if (client.isSessionExpired()) {
75
- // Check if refresh token is still valid
76
- if (!client.isRefreshSessionExpired()) {
77
- await client.refreshSession();
78
- // Update stored session data
79
- localStorage.setItem('mezon_session', JSON.stringify(client.exportSession()));
80
- } else {
81
- // Both tokens expired - need to re-authenticate
82
- console.log('Session fully expired, please login again');
83
- }
84
- }
85
-
86
- // Access tokens and session directly if needed
87
- const token = client.getToken();
88
- const refreshToken = client.getRefreshToken();
89
- const session = client.getSession();
90
- ```
91
-
92
- ### 4. Connect to Real-time Socket
93
-
94
- ```typescript
95
- import { LightSocket, SocketError } from 'mezon-light-sdk';
96
-
97
- const socket = new LightSocket(client, client.session);
98
-
99
- await socket.connect({
100
- onError: (error) => console.error('Socket error:', error),
101
- onDisconnect: () => console.log('Socket disconnected'),
102
- verbose: false // set to true for debug logging
103
- });
104
-
105
- // Check connection status
106
- console.log('Connected:', socket.isConnected);
107
- ```
108
-
109
- ### 5. Listen for Messages
110
-
111
- ```typescript
112
- // Register a message handler (returns unsubscribe function)
113
- const unsubscribe = socket.onChannelMessage((message) => {
114
- console.log(`Message from ${message.sender_id}: ${message.content}`);
115
- console.log('Channel:', message.channel_id);
116
- console.log('Timestamp:', message.create_time_seconds);
117
- });
118
-
119
- // Alternative: use setChannelMessageHandler (does not return unsubscribe)
120
- socket.setChannelMessageHandler((message) => {
121
- console.log('Received:', message.content);
122
- });
123
-
124
- // Multiple handlers can be registered
125
- const unsubscribe2 = socket.onChannelMessage((message) => {
126
- // Another handler for the same messages
127
- });
128
-
129
- // Unsubscribe when no longer needed
130
- unsubscribe();
131
- unsubscribe2();
132
- ```
133
-
134
- ### 6. Create and Join Channels
135
-
136
- ```typescript
137
- // Create a DM with a single user
138
- const dmChannel = await client.createDM('peer-user-id');
139
- await socket.joinDMChannel(dmChannel.channel_id!);
140
-
141
- // Create a group DM with multiple users
142
- const groupDM = await client.createGroupDM(['user-1', 'user-2', 'user-3']);
143
- await socket.joinGroupChannel(groupDM.channel_id!);
144
-
145
- // Leave channels
146
- await socket.leaveDMChannel(dmChannel.channel_id!);
147
- await socket.leaveGroupChannel(groupDM.channel_id!);
148
- ```
149
-
150
- ### 7. Send Messages
151
-
152
- ```typescript
153
- // Send a DM message
154
- await socket.sendDM({
155
- channelId: 'channel-123',
156
- content: { t: 'Hello, world!' },
157
- hideLink: false // optional, whether to hide link previews
158
- });
159
-
160
- // Send a group message
161
- await socket.sendGroup({
162
- channelId: 'group-channel-456',
163
- content: { t: 'Hello everyone!' },
164
- attachments: [
165
- {
166
- filename: 'image.png',
167
- url: 'https://cdn.mezon.ai/path/to/image.png',
168
- filetype: 'image/png',
169
- size: 42439,
170
- width: 716,
171
- height: 522
172
- }
173
- ],
174
- hideLink: true
175
- });
176
- ```
177
-
178
- ### 8. Disconnect
179
-
180
- ```typescript
181
- // Disconnect when done
182
- socket.disconnect();
183
- ```
184
-
185
- ## API Reference
186
-
187
- ### LightClient
188
-
189
- | Property/Method | Description |
190
- |-----------------|-------------|
191
- | `LightClient.authenticate(config)` | Static: Authenticate with ID token |
192
- | `LightClient.initClient(config)` | Static: Initialize from existing tokens |
193
- | `client.userId` | Get current user ID |
194
- | `client.session` | Get underlying Session object |
195
- | `client.client` | Get underlying MezonApi client |
196
- | `client.createDM(peerId)` | Create a DM channel with one user |
197
- | `client.createGroupDM(userIds)` | Create a group DM with multiple users |
198
- | `client.refreshSession()` | Refresh the session using refresh token |
199
- | `client.isSessionExpired()` | Check if session token is expired |
200
- | `client.isRefreshSessionExpired()` | Check if refresh token is expired |
201
- | `client.getToken()` | Get the current auth token |
202
- | `client.getRefreshToken()` | Get the refresh token |
203
- | `client.getSession()` | Get the current session object |
204
- | `client.exportSession()` | Export session data for persistence |
205
- | `client.createSocket(verbose?, adapter?, timeout?)` | Create a raw socket instance |
206
-
207
- ### LightSocket
208
-
209
- | Property/Method | Description |
210
- |-----------------|-------------|
211
- | `new LightSocket(client, session)` | Create a new socket instance |
212
- | `socket.connect(options?)` | Connect to real-time server |
213
- | `socket.disconnect()` | Disconnect from server |
214
- | `socket.isConnected` | Check if socket is connected |
215
- | `socket.socket` | Get underlying Socket (throws if not connected) |
216
- | `socket.onChannelMessage(handler)` | Register message handler, returns unsubscribe fn |
217
- | `socket.setChannelMessageHandler(handler)` | Register message handler (alias) |
218
- | `socket.joinDMChannel(channelId)` | Join a DM channel |
219
- | `socket.joinGroupChannel(channelId)` | Join a group channel |
220
- | `socket.leaveDMChannel(channelId)` | Leave a DM channel |
221
- | `socket.leaveGroupChannel(channelId)` | Leave a group channel |
222
- | `socket.sendDM(payload)` | Send a DM message |
223
- | `socket.sendGroup(payload)` | Send a group message |
224
- | `socket.setErrorHandler(handler)` | Set custom error handler |
225
-
226
- ### Types
227
-
228
- ```typescript
229
- interface ClientInitConfig {
230
- token: string; // Auth token
231
- refresh_token: string; // Refresh token
232
- api_url: string; // API URL
233
- user_id: string; // User ID
234
- serverkey?: string; // Optional server key
235
- }
236
-
237
- interface AuthenticateConfig {
238
- id_token: string; // ID token from provider
239
- user_id: string; // User ID
240
- username: string; // Username
241
- serverkey?: string; // Optional server key
242
- gateway_url?: string; // Optional gateway URL
243
- }
244
-
245
- interface SendMessagePayload {
246
- channelId: string; // Target channel
247
- content: unknown; // Message content
248
- attachments?: ApiMessageAttachment[]; // Optional attachments
249
- hideLink?: boolean; // Hide link previews
250
- }
251
-
252
- interface SocketConnectOptions {
253
- onError?: (error: unknown) => void; // Error callback
254
- onDisconnect?: () => void; // Disconnect callback
255
- verbose?: boolean; // Enable debug logging
256
- }
257
- ```
258
-
1
+ # Mezon Light SDK
2
+
3
+ A lightweight SDK for Mezon chat integration, providing simple APIs for authentication, real-time messaging, and direct message management.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install mezon-light-sdk
9
+ ```
10
+
11
+ ## Features
12
+
13
+ - 🔐 Simple authentication with ID tokens
14
+ - 💬 Real-time messaging via WebSocket (protobuf-based)
15
+ - 📨 Direct message (DM) and group DM support
16
+ - 🔄 Automatic session management with token refresh
17
+ - 📎 File upload and attachment support (presigned URLs)
18
+ - 🎯 TypeScript-first with full type definitions
19
+ - ⚡ Exponential backoff for socket connection reliability
20
+
21
+ ## Quick Start
22
+
23
+ ### 1. Authenticate with ID Token
24
+
25
+ ```typescript
26
+ import { LightClient, AuthenticationError } from 'mezon-light-sdk';
27
+
28
+ try {
29
+ const client = await LightClient.authenticate({
30
+ id_token: 'your-id-token',
31
+ user_id: 'user-123',
32
+ username: 'johndoe',
33
+ serverkey: 'your-server-key', // optional, uses DEFAULT_SERVER_KEY
34
+ gateway_url: 'https://gw.mezon.ai' // optional, uses MEZON_GW_URL
35
+ });
36
+
37
+ console.log('Authenticated as:', client.userId);
38
+ } catch (error) {
39
+ if (error instanceof AuthenticationError) {
40
+ console.error('Auth failed:', error.message, error.statusCode);
41
+ }
42
+ }
43
+ ```
44
+
45
+ ### 2. Restore Session from Storage
46
+
47
+ After login, persist the session data and restore it later:
48
+
49
+ ```typescript
50
+ import { LightClient, SessionError } from 'mezon-light-sdk';
51
+
52
+ // Export session for storage
53
+ const sessionData = client.exportSession();
54
+ // Returns: { token, refresh_token, api_url, user_id }
55
+ localStorage.setItem('mezon_session', JSON.stringify(sessionData));
56
+
57
+ // Later: restore from storage
58
+ try {
59
+ const savedData = JSON.parse(localStorage.getItem('mezon_session')!);
60
+ const client = LightClient.initClient(savedData);
61
+ } catch (error) {
62
+ if (error instanceof SessionError) {
63
+ console.error('Session restore failed:', error.message);
64
+ }
65
+ }
66
+ ```
67
+
68
+ ### 3. Session Management
69
+
70
+ Check and refresh the session before connecting:
71
+
72
+ ```typescript
73
+ // Check if session token is expired
74
+ if (client.isSessionExpired()) {
75
+ // Check if refresh token is still valid
76
+ if (!client.isRefreshSessionExpired()) {
77
+ await client.refreshSession();
78
+ // Update stored session data
79
+ localStorage.setItem('mezon_session', JSON.stringify(client.exportSession()));
80
+ } else {
81
+ // Both tokens expired - need to re-authenticate
82
+ console.log('Session fully expired, please login again');
83
+ }
84
+ }
85
+
86
+ // Access tokens and session directly if needed
87
+ const token = client.getToken();
88
+ const refreshToken = client.getRefreshToken();
89
+ const session = client.getSession();
90
+ ```
91
+
92
+ ### 4. Connect to Real-time Socket
93
+
94
+ ```typescript
95
+ import { LightSocket, SocketError } from 'mezon-light-sdk';
96
+
97
+ const socket = new LightSocket(client, client.session);
98
+
99
+ await socket.connect({
100
+ onError: (error) => console.error('Socket error:', error),
101
+ onDisconnect: () => console.log('Socket disconnected'),
102
+ verbose: false // set to true for debug logging
103
+ });
104
+
105
+ // Check connection status
106
+ console.log('Connected:', socket.isConnected);
107
+ ```
108
+
109
+ ### 5. Listen for Messages
110
+
111
+ ```typescript
112
+ // Register a message handler (returns unsubscribe function)
113
+ const unsubscribe = socket.onChannelMessage((message) => {
114
+ console.log(`Message from ${message.sender_id}: ${message.content}`);
115
+ console.log('Channel:', message.channel_id);
116
+ console.log('Timestamp:', message.create_time_seconds);
117
+ });
118
+
119
+ // Alternative: use setChannelMessageHandler (does not return unsubscribe)
120
+ socket.setChannelMessageHandler((message) => {
121
+ console.log('Received:', message.content);
122
+ });
123
+
124
+ // Multiple handlers can be registered
125
+ const unsubscribe2 = socket.onChannelMessage((message) => {
126
+ // Another handler for the same messages
127
+ });
128
+
129
+ // Unsubscribe when no longer needed
130
+ unsubscribe();
131
+ unsubscribe2();
132
+ ```
133
+
134
+ ### 6. Create and Join Channels
135
+
136
+ ```typescript
137
+ // Create a DM with a single user
138
+ const dmChannel = await client.createDM('peer-user-id');
139
+ await socket.joinDMChannel(dmChannel.channel_id!);
140
+
141
+ // Create a group DM with multiple users
142
+ const groupDM = await client.createGroupDM(['user-1', 'user-2', 'user-3']);
143
+ await socket.joinGroupChannel(groupDM.channel_id!);
144
+
145
+ // Leave channels
146
+ await socket.leaveDMChannel(dmChannel.channel_id!);
147
+ await socket.leaveGroupChannel(groupDM.channel_id!);
148
+ ```
149
+
150
+ ### 7. Send Messages
151
+
152
+ ```typescript
153
+ // Send a DM message
154
+ await socket.sendDM({
155
+ channelId: 'channel-123',
156
+ content: { t: 'Hello, world!' },
157
+ hideLink: false // optional, whether to hide link previews
158
+ });
159
+
160
+ // Send a group message
161
+ await socket.sendGroup({
162
+ channelId: 'group-channel-456',
163
+ content: { t: 'Hello everyone!' },
164
+ attachments: [
165
+ {
166
+ filename: 'image.png',
167
+ url: 'https://cdn.mezon.ai/path/to/image.png',
168
+ filetype: 'image/png',
169
+ size: 42439,
170
+ width: 716,
171
+ height: 522
172
+ }
173
+ ],
174
+ hideLink: true
175
+ });
176
+ ```
177
+
178
+ ### 8. Upload Attachments
179
+
180
+ **Upload Flow (Presigned URL):**
181
+
182
+ Mezon uses **Presigned URLs** for secure file uploads:
183
+ 1. Client calls `uploadAttachment()` with file metadata → Server returns a **Presigned URL** (with temporary credentials in query params)
184
+ 2. Client uses the Presigned URL to **PUT file directly to CDN** (bypassing backend)
185
+ 3. After upload, Client **extracts the base URL** (removes query params) to use in message attachment
186
+
187
+ > **Note:** The SDK supports uploading **any file type** (images, documents, archives, etc.). when uploading non-image files, you can omit the `width` and `height` parameters.
188
+
189
+ **Example:**
190
+ - Presigned URL: `https://cdn.mezon.ai/file.png?X-Amz-Signature=...` → Used for **upload**
191
+ - CDN URL: `https://cdn.mezon.ai/file.png` Used in **message**
192
+
193
+ ```typescript
194
+ import * as fs from 'fs';
195
+ import * as path from 'path';
196
+
197
+ // Step 1: Get file information
198
+ const imagePath = path.join(__dirname, 'image.png');
199
+ const stats = fs.statSync(imagePath);
200
+
201
+ // Step 2: Request presigned URL from server
202
+ const uploadResponse = await client.uploadAttachment({
203
+ filename: 'image.png',
204
+ filetype: 'image/png',
205
+ size: stats.size,
206
+ width: 800,
207
+ height: 600
208
+ });
209
+
210
+ // uploadResponse.url = "https://cdn.mezon.ai/file.png?X-Amz-Algorithm=..."
211
+
212
+ // Step 3: Upload file to CDN via presigned URL
213
+ const fileBuffer = fs.readFileSync(imagePath);
214
+ await fetch(uploadResponse.url!, {
215
+ method: 'PUT',
216
+ headers: { 'Content-Type': 'image/png' },
217
+ body: fileBuffer
218
+ });
219
+
220
+ // Step 4: Extract clean CDN URL (remove query params)
221
+ const urlObj = new URL(uploadResponse.url!);
222
+ const cdnUrl = `${urlObj.protocol}//${urlObj.host}${urlObj.pathname}`;
223
+ // cdnUrl = "https://cdn.mezon.ai/file.png"
224
+
225
+ // Step 5: Send message with attachment
226
+ await socket.sendDM({
227
+ channelId: 'channel-123',
228
+ content: { t: 'Check out this image!' },
229
+ attachments: [{
230
+ filename: 'image.png',
231
+ url: cdnUrl, // Use clean CDN URL
232
+ filetype: 'image/png',
233
+ size: stats.size,
234
+ width: 800,
235
+ height: 600
236
+ }]
237
+ });
238
+ ```
239
+
240
+ **⚠️ Important:**
241
+ - Presigned URLs have **short expiration** (typically 10-60s), upload immediately after receiving
242
+ - Only use **clean CDN URL** (without query params) in message attachment
243
+
244
+
245
+ ### 9. Disconnect
246
+
247
+ ```typescript
248
+ // Disconnect when done
249
+ socket.disconnect();
250
+ ```
251
+
252
+ ## API Reference
253
+
254
+ ### LightClient
255
+
256
+ | Property/Method | Description |
257
+ |-----------------|-------------|
258
+ | `LightClient.authenticate(config)` | Static: Authenticate with ID token |
259
+ | `LightClient.initClient(config)` | Static: Initialize from existing tokens |
260
+ | `client.userId` | Get current user ID |
261
+ | `client.session` | Get underlying Session object |
262
+ | `client.client` | Get underlying MezonApi client |
263
+ | `client.createDM(peerId)` | Create a DM channel with one user |
264
+ | `client.createGroupDM(userIds)` | Create a group DM with multiple users |
265
+ | `client.uploadAttachment(request)` | Upload file and get presigned URL + CDN URL |
266
+ | `client.refreshSession()` | Refresh the session using refresh token |
267
+ | `client.isSessionExpired()` | Check if session token is expired |
268
+ | `client.isRefreshSessionExpired()` | Check if refresh token is expired |
269
+ | `client.getToken()` | Get the current auth token |
270
+ | `client.getRefreshToken()` | Get the refresh token |
271
+ | `client.getSession()` | Get the current session object |
272
+ | `client.exportSession()` | Export session data for persistence |
273
+ | `client.createSocket(verbose?, adapter?, timeout?)` | Create a raw socket instance |
274
+
275
+
276
+ ### LightSocket
277
+
278
+ | Property/Method | Description |
279
+ |-----------------|-------------|
280
+ | `new LightSocket(client, session)` | Create a new socket instance |
281
+ | `socket.connect(options?)` | Connect to real-time server |
282
+ | `socket.disconnect()` | Disconnect from server |
283
+ | `socket.isConnected` | Check if socket is connected |
284
+ | `socket.socket` | Get underlying Socket (throws if not connected) |
285
+ | `socket.onChannelMessage(handler)` | Register message handler, returns unsubscribe fn |
286
+ | `socket.setChannelMessageHandler(handler)` | Register message handler (alias) |
287
+ | `socket.joinDMChannel(channelId)` | Join a DM channel |
288
+ | `socket.joinGroupChannel(channelId)` | Join a group channel |
289
+ | `socket.leaveDMChannel(channelId)` | Leave a DM channel |
290
+ | `socket.leaveGroupChannel(channelId)` | Leave a group channel |
291
+ | `socket.sendDM(payload)` | Send a DM message |
292
+ | `socket.sendGroup(payload)` | Send a group message |
293
+ | `socket.setErrorHandler(handler)` | Set custom error handler |
294
+
295
+ ### Types
296
+
297
+ ```typescript
298
+ interface ClientInitConfig {
299
+ token: string; // Auth token
300
+ refresh_token: string; // Refresh token
301
+ api_url: string; // API URL
302
+ user_id: string; // User ID
303
+ serverkey?: string; // Optional server key
304
+ }
305
+
306
+ interface AuthenticateConfig {
307
+ id_token: string; // ID token from provider
308
+ user_id: string; // User ID
309
+ username: string; // Username
310
+ serverkey?: string; // Optional server key
311
+ gateway_url?: string; // Optional gateway URL
312
+ }
313
+
314
+ interface SendMessagePayload {
315
+ channelId: string; // Target channel
316
+ content: unknown; // Message content
317
+ attachments?: ApiMessageAttachment[]; // Optional attachments
318
+ hideLink?: boolean; // Hide link previews
319
+ }
320
+
321
+ interface SocketConnectOptions {
322
+ onError?: (error: unknown) => void; // Error callback
323
+ onDisconnect?: () => void; // Disconnect callback
324
+ verbose?: boolean; // Enable debug logging
325
+ }
326
+
327
+ interface ApiUploadAttachmentRequest {
328
+ filename?: string; // File name
329
+ filetype?: string; // MIME type (e.g., 'image/png')
330
+ size?: number; // File size in bytes
331
+ width?: number; // Image width (for images)
332
+ height?: number; // Image height (for images)
333
+ }
334
+
335
+ interface ApiUploadAttachment {
336
+ filename?: string; // Uploaded file name
337
+ url?: string; // Presigned URL (with query params)
338
+ }
339
+
340
+ interface ApiMessageAttachment {
341
+ filename?: string; // File name
342
+ url?: string; // Clean CDN URL (without query params)
343
+ filetype?: string; // MIME type
344
+ size?: number; // File size in bytes
345
+ width?: number; // Image width
346
+ height?: number; // Image height
347
+ thumbnail?: string; // Thumbnail URL (optional)
348
+ duration?: number; // Video duration in seconds (optional)
349
+ }
350
+ ```
351
+
259
352
  ---