chatly-sdk 1.0.0 → 2.0.0
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/CONTRIBUTING.md +658 -0
- package/IMPROVEMENTS.md +402 -0
- package/LICENSE +21 -0
- package/README.md +1576 -162
- package/dist/index.d.ts +502 -11
- package/dist/index.js +1619 -66
- package/examples/01-basic-chat/README.md +61 -0
- package/examples/01-basic-chat/index.js +58 -0
- package/examples/01-basic-chat/package.json +13 -0
- package/examples/02-group-chat/README.md +78 -0
- package/examples/02-group-chat/index.js +76 -0
- package/examples/02-group-chat/package.json +13 -0
- package/examples/03-offline-messaging/README.md +73 -0
- package/examples/03-offline-messaging/index.js +80 -0
- package/examples/03-offline-messaging/package.json +13 -0
- package/examples/04-live-chat/README.md +80 -0
- package/examples/04-live-chat/index.js +114 -0
- package/examples/04-live-chat/package.json +13 -0
- package/examples/05-hybrid-messaging/README.md +71 -0
- package/examples/05-hybrid-messaging/index.js +106 -0
- package/examples/05-hybrid-messaging/package.json +13 -0
- package/examples/06-postgresql-integration/README.md +101 -0
- package/examples/06-postgresql-integration/adapters/groupStore.js +73 -0
- package/examples/06-postgresql-integration/adapters/messageStore.js +47 -0
- package/examples/06-postgresql-integration/adapters/userStore.js +40 -0
- package/examples/06-postgresql-integration/index.js +92 -0
- package/examples/06-postgresql-integration/package.json +14 -0
- package/examples/06-postgresql-integration/schema.sql +58 -0
- package/examples/08-customer-support/README.md +70 -0
- package/examples/08-customer-support/index.js +104 -0
- package/examples/08-customer-support/package.json +13 -0
- package/examples/README.md +105 -0
- package/jest.config.cjs +28 -0
- package/package.json +15 -6
- package/src/chat/ChatSession.ts +160 -3
- package/src/chat/GroupSession.ts +108 -1
- package/src/constants.ts +61 -0
- package/src/crypto/e2e.ts +9 -20
- package/src/crypto/utils.ts +3 -1
- package/src/index.ts +530 -63
- package/src/models/mediaTypes.ts +62 -0
- package/src/models/message.ts +4 -1
- package/src/storage/adapters.ts +36 -0
- package/src/storage/localStorage.ts +49 -0
- package/src/storage/s3Storage.ts +84 -0
- package/src/stores/adapters.ts +2 -0
- package/src/stores/memory/messageStore.ts +8 -0
- package/src/transport/adapters.ts +51 -1
- package/src/transport/memoryTransport.ts +75 -13
- package/src/transport/websocketClient.ts +269 -21
- package/src/transport/websocketServer.ts +26 -26
- package/src/utils/errors.ts +97 -0
- package/src/utils/logger.ts +96 -0
- package/src/utils/mediaUtils.ts +235 -0
- package/src/utils/messageQueue.ts +162 -0
- package/src/utils/validation.ts +99 -0
- package/test/crypto.test.ts +122 -35
- package/test/sdk.test.ts +276 -0
- package/test/validation.test.ts +64 -0
- package/tsconfig.json +11 -10
- package/tsconfig.test.json +11 -0
- package/src/ChatManager.ts +0 -103
- package/src/crypto/keyManager.ts +0 -28
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
|
|
1
3
|
interface User {
|
|
2
4
|
id: string;
|
|
3
5
|
username: string;
|
|
@@ -9,7 +11,59 @@ interface StoredUser extends User {
|
|
|
9
11
|
createdAt: number;
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Media types supported by the SDK
|
|
16
|
+
*/
|
|
17
|
+
declare enum MediaType {
|
|
18
|
+
IMAGE = "image",
|
|
19
|
+
AUDIO = "audio",
|
|
20
|
+
VIDEO = "video",
|
|
21
|
+
DOCUMENT = "document"
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Media metadata
|
|
25
|
+
*/
|
|
26
|
+
interface MediaMetadata {
|
|
27
|
+
filename: string;
|
|
28
|
+
mimeType: string;
|
|
29
|
+
size: number;
|
|
30
|
+
width?: number;
|
|
31
|
+
height?: number;
|
|
32
|
+
duration?: number;
|
|
33
|
+
thumbnail?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Media attachment
|
|
37
|
+
*/
|
|
38
|
+
interface MediaAttachment {
|
|
39
|
+
type: MediaType;
|
|
40
|
+
data?: string | undefined;
|
|
41
|
+
iv?: string | undefined;
|
|
42
|
+
metadata: MediaMetadata;
|
|
43
|
+
storage?: 'local' | 's3' | undefined;
|
|
44
|
+
storageKey?: string | undefined;
|
|
45
|
+
url?: string | undefined;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Supported MIME types
|
|
49
|
+
*/
|
|
50
|
+
declare const SUPPORTED_MIME_TYPES: {
|
|
51
|
+
image: string[];
|
|
52
|
+
audio: string[];
|
|
53
|
+
video: string[];
|
|
54
|
+
document: string[];
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* File size limits (in bytes)
|
|
58
|
+
*/
|
|
59
|
+
declare const FILE_SIZE_LIMITS: {
|
|
60
|
+
image: number;
|
|
61
|
+
audio: number;
|
|
62
|
+
video: number;
|
|
63
|
+
document: number;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
type MessageType = "text" | "media" | "system";
|
|
13
67
|
interface Message {
|
|
14
68
|
id: string;
|
|
15
69
|
senderId: string;
|
|
@@ -19,6 +73,7 @@ interface Message {
|
|
|
19
73
|
iv: string;
|
|
20
74
|
timestamp: number;
|
|
21
75
|
type: MessageType;
|
|
76
|
+
media?: MediaAttachment;
|
|
22
77
|
}
|
|
23
78
|
|
|
24
79
|
interface Group {
|
|
@@ -36,8 +91,10 @@ interface UserStoreAdapter {
|
|
|
36
91
|
}
|
|
37
92
|
interface MessageStoreAdapter {
|
|
38
93
|
create(message: Message): Promise<Message>;
|
|
94
|
+
findById(id: string): Promise<Message | undefined>;
|
|
39
95
|
listByUser(userId: string): Promise<Message[]>;
|
|
40
96
|
listByGroup(groupId: string): Promise<Message[]>;
|
|
97
|
+
delete(id: string): Promise<void>;
|
|
41
98
|
}
|
|
42
99
|
interface GroupStoreAdapter {
|
|
43
100
|
create(group: Group): Promise<Group>;
|
|
@@ -45,19 +102,138 @@ interface GroupStoreAdapter {
|
|
|
45
102
|
list(): Promise<Group[]>;
|
|
46
103
|
}
|
|
47
104
|
|
|
105
|
+
/**
|
|
106
|
+
* SDK Configuration Constants
|
|
107
|
+
*/
|
|
108
|
+
declare const SUPPORTED_CURVE = "prime256v1";
|
|
109
|
+
declare const ALGORITHM = "aes-256-gcm";
|
|
110
|
+
declare const IV_LENGTH = 12;
|
|
111
|
+
declare const SALT_LENGTH = 16;
|
|
112
|
+
declare const KEY_LENGTH = 32;
|
|
113
|
+
declare const TAG_LENGTH = 16;
|
|
114
|
+
declare const PBKDF2_ITERATIONS = 100000;
|
|
115
|
+
declare const USERNAME_MIN_LENGTH = 3;
|
|
116
|
+
declare const USERNAME_MAX_LENGTH = 20;
|
|
117
|
+
declare const MESSAGE_MAX_LENGTH = 10000;
|
|
118
|
+
declare const GROUP_NAME_MAX_LENGTH = 100;
|
|
119
|
+
declare const GROUP_MIN_MEMBERS = 2;
|
|
120
|
+
declare const GROUP_MAX_MEMBERS = 256;
|
|
121
|
+
declare const RECONNECT_MAX_ATTEMPTS = 5;
|
|
122
|
+
declare const RECONNECT_BASE_DELAY = 1000;
|
|
123
|
+
declare const RECONNECT_MAX_DELAY = 30000;
|
|
124
|
+
declare const HEARTBEAT_INTERVAL = 30000;
|
|
125
|
+
declare const CONNECTION_TIMEOUT = 10000;
|
|
126
|
+
declare const MAX_QUEUE_SIZE = 1000;
|
|
127
|
+
declare const MESSAGE_RETRY_ATTEMPTS = 3;
|
|
128
|
+
declare const MESSAGE_RETRY_DELAY = 2000;
|
|
129
|
+
declare const EVENTS: {
|
|
130
|
+
readonly MESSAGE_SENT: "message:sent";
|
|
131
|
+
readonly MESSAGE_RECEIVED: "message:received";
|
|
132
|
+
readonly MESSAGE_FAILED: "message:failed";
|
|
133
|
+
readonly CONNECTION_STATE_CHANGED: "connection:state";
|
|
134
|
+
readonly SESSION_CREATED: "session:created";
|
|
135
|
+
readonly GROUP_CREATED: "group:created";
|
|
136
|
+
readonly ERROR: "error";
|
|
137
|
+
readonly USER_CREATED: "user:created";
|
|
138
|
+
};
|
|
139
|
+
declare enum ConnectionState {
|
|
140
|
+
DISCONNECTED = "disconnected",
|
|
141
|
+
CONNECTING = "connecting",
|
|
142
|
+
CONNECTED = "connected",
|
|
143
|
+
RECONNECTING = "reconnecting",
|
|
144
|
+
FAILED = "failed"
|
|
145
|
+
}
|
|
146
|
+
declare enum MessageStatus {
|
|
147
|
+
PENDING = "pending",
|
|
148
|
+
SENT = "sent",
|
|
149
|
+
DELIVERED = "delivered",
|
|
150
|
+
FAILED = "failed"
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Transport adapter interface for network communication
|
|
155
|
+
*/
|
|
48
156
|
interface TransportAdapter {
|
|
157
|
+
/**
|
|
158
|
+
* Connect to the transport
|
|
159
|
+
* @param userId - User ID to connect as
|
|
160
|
+
*/
|
|
49
161
|
connect(userId: string): Promise<void>;
|
|
162
|
+
/**
|
|
163
|
+
* Disconnect from the transport
|
|
164
|
+
*/
|
|
165
|
+
disconnect(): Promise<void>;
|
|
166
|
+
/**
|
|
167
|
+
* Reconnect to the transport
|
|
168
|
+
*/
|
|
169
|
+
reconnect(): Promise<void>;
|
|
170
|
+
/**
|
|
171
|
+
* Send a message
|
|
172
|
+
* @param message - Message to send
|
|
173
|
+
*/
|
|
50
174
|
send(message: Message): Promise<void>;
|
|
175
|
+
/**
|
|
176
|
+
* Register a message handler
|
|
177
|
+
* @param handler - Function to call when a message is received
|
|
178
|
+
*/
|
|
51
179
|
onMessage(handler: (message: Message) => void): void;
|
|
180
|
+
/**
|
|
181
|
+
* Register a connection state change handler
|
|
182
|
+
* @param handler - Function to call when connection state changes
|
|
183
|
+
*/
|
|
184
|
+
onConnectionStateChange?(handler: (state: ConnectionState) => void): void;
|
|
185
|
+
/**
|
|
186
|
+
* Register an error handler
|
|
187
|
+
* @param handler - Function to call when an error occurs
|
|
188
|
+
*/
|
|
189
|
+
onError?(handler: (error: Error) => void): void;
|
|
190
|
+
/**
|
|
191
|
+
* Get the current connection state
|
|
192
|
+
*/
|
|
193
|
+
getConnectionState(): ConnectionState;
|
|
194
|
+
/**
|
|
195
|
+
* Check if transport is connected
|
|
196
|
+
*/
|
|
197
|
+
isConnected(): boolean;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
interface StorageUploadResult {
|
|
201
|
+
storageKey: string;
|
|
202
|
+
url?: string;
|
|
203
|
+
}
|
|
204
|
+
interface StorageProvider {
|
|
205
|
+
/**
|
|
206
|
+
* Name of the storage provider (e.g., 'local', 's3')
|
|
207
|
+
*/
|
|
208
|
+
readonly name: string;
|
|
209
|
+
/**
|
|
210
|
+
* Upload data to storage
|
|
211
|
+
* @param data Base64 encoded data or Buffer
|
|
212
|
+
* @param filename Desired filename or path
|
|
213
|
+
* @param mimeType MIME type of the file
|
|
214
|
+
*/
|
|
215
|
+
upload(data: string | Buffer, filename: string, mimeType: string): Promise<StorageUploadResult>;
|
|
216
|
+
/**
|
|
217
|
+
* Download data from storage
|
|
218
|
+
* @param storageKey Key/path of the file in storage
|
|
219
|
+
* @returns Base64 encoded data
|
|
220
|
+
*/
|
|
221
|
+
download(storageKey: string): Promise<string>;
|
|
222
|
+
/**
|
|
223
|
+
* Delete data from storage
|
|
224
|
+
* @param storageKey Key/path of the file in storage
|
|
225
|
+
*/
|
|
226
|
+
delete(storageKey: string): Promise<void>;
|
|
52
227
|
}
|
|
53
228
|
|
|
54
229
|
declare class ChatSession {
|
|
55
230
|
readonly id: string;
|
|
56
231
|
readonly userA: User;
|
|
57
232
|
readonly userB: User;
|
|
233
|
+
private storageProvider?;
|
|
58
234
|
private sharedSecret;
|
|
59
235
|
private ephemeralKeyPair;
|
|
60
|
-
constructor(id: string, userA: User, userB: User);
|
|
236
|
+
constructor(id: string, userA: User, userB: User, storageProvider?: StorageProvider | undefined);
|
|
61
237
|
/**
|
|
62
238
|
* Initialize the session by deriving the shared secret
|
|
63
239
|
* ECDH is commutative, so we can use either user's keys
|
|
@@ -71,16 +247,29 @@ declare class ChatSession {
|
|
|
71
247
|
* Encrypt a message for this session
|
|
72
248
|
*/
|
|
73
249
|
encrypt(plaintext: string, senderId: string): Promise<Message>;
|
|
250
|
+
/**
|
|
251
|
+
* Encrypt a media message for this session
|
|
252
|
+
*/
|
|
253
|
+
encryptMedia(plaintext: string, media: MediaAttachment, senderId: string): Promise<Message>;
|
|
74
254
|
/**
|
|
75
255
|
* Decrypt a message in this session
|
|
76
256
|
*/
|
|
77
257
|
decrypt(message: Message, user: User): Promise<string>;
|
|
258
|
+
private deriveLegacySecret;
|
|
259
|
+
/**
|
|
260
|
+
* Decrypt a media message in this session
|
|
261
|
+
*/
|
|
262
|
+
decryptMedia(message: Message, user: User): Promise<{
|
|
263
|
+
text: string;
|
|
264
|
+
media: MediaAttachment;
|
|
265
|
+
}>;
|
|
78
266
|
}
|
|
79
267
|
|
|
80
268
|
declare class GroupSession {
|
|
81
269
|
readonly group: Group;
|
|
270
|
+
private storageProvider?;
|
|
82
271
|
private groupKey;
|
|
83
|
-
constructor(group: Group);
|
|
272
|
+
constructor(group: Group, storageProvider?: StorageProvider | undefined);
|
|
84
273
|
/**
|
|
85
274
|
* Initialize the session by deriving the group key
|
|
86
275
|
*/
|
|
@@ -89,11 +278,57 @@ declare class GroupSession {
|
|
|
89
278
|
* Encrypt a message for this group
|
|
90
279
|
*/
|
|
91
280
|
encrypt(plaintext: string, senderId: string): Promise<Message>;
|
|
281
|
+
/**
|
|
282
|
+
* Encrypt a media message for this group
|
|
283
|
+
*/
|
|
284
|
+
encryptMedia(plaintext: string, media: MediaAttachment, senderId: string): Promise<Message>;
|
|
92
285
|
/**
|
|
93
286
|
* Decrypt a message in this group
|
|
94
287
|
*/
|
|
95
288
|
decrypt(message: Message): Promise<string>;
|
|
289
|
+
/**
|
|
290
|
+
* Decrypt a media message in this group
|
|
291
|
+
*/
|
|
292
|
+
decryptMedia(message: Message): Promise<{
|
|
293
|
+
text: string;
|
|
294
|
+
media: MediaAttachment;
|
|
295
|
+
}>;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Log levels
|
|
300
|
+
*/
|
|
301
|
+
declare enum LogLevel {
|
|
302
|
+
DEBUG = 0,
|
|
303
|
+
INFO = 1,
|
|
304
|
+
WARN = 2,
|
|
305
|
+
ERROR = 3,
|
|
306
|
+
NONE = 4
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Logger configuration
|
|
310
|
+
*/
|
|
311
|
+
interface LoggerConfig {
|
|
312
|
+
level: LogLevel;
|
|
313
|
+
prefix?: string;
|
|
314
|
+
timestamp?: boolean;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Simple structured logger
|
|
318
|
+
*/
|
|
319
|
+
declare class Logger {
|
|
320
|
+
private config;
|
|
321
|
+
constructor(config?: Partial<LoggerConfig>);
|
|
322
|
+
private shouldLog;
|
|
323
|
+
private formatMessage;
|
|
324
|
+
debug(message: string, data?: unknown): void;
|
|
325
|
+
info(message: string, data?: unknown): void;
|
|
326
|
+
warn(message: string, data?: unknown): void;
|
|
327
|
+
error(message: string, error?: Error | unknown): void;
|
|
328
|
+
setLevel(level: LogLevel): void;
|
|
329
|
+
getLevel(): LogLevel;
|
|
96
330
|
}
|
|
331
|
+
declare const logger: Logger;
|
|
97
332
|
|
|
98
333
|
declare class InMemoryUserStore implements UserStoreAdapter {
|
|
99
334
|
private users;
|
|
@@ -106,8 +341,10 @@ declare class InMemoryUserStore implements UserStoreAdapter {
|
|
|
106
341
|
declare class InMemoryMessageStore implements MessageStoreAdapter {
|
|
107
342
|
private messages;
|
|
108
343
|
create(message: Message): Promise<Message>;
|
|
344
|
+
findById(id: string): Promise<Message | undefined>;
|
|
109
345
|
listByUser(userId: string): Promise<Message[]>;
|
|
110
346
|
listByGroup(groupId: string): Promise<Message[]>;
|
|
347
|
+
delete(id: string): Promise<void>;
|
|
111
348
|
}
|
|
112
349
|
|
|
113
350
|
declare class InMemoryGroupStore implements GroupStoreAdapter {
|
|
@@ -117,28 +354,231 @@ declare class InMemoryGroupStore implements GroupStoreAdapter {
|
|
|
117
354
|
list(): Promise<Group[]>;
|
|
118
355
|
}
|
|
119
356
|
|
|
120
|
-
|
|
357
|
+
/**
|
|
358
|
+
* In-memory transport for testing (no actual network communication)
|
|
359
|
+
*/
|
|
121
360
|
declare class InMemoryTransport implements TransportAdapter {
|
|
122
|
-
private
|
|
123
|
-
private
|
|
124
|
-
|
|
361
|
+
private messageHandler;
|
|
362
|
+
private connectionState;
|
|
363
|
+
private stateHandler;
|
|
364
|
+
private errorHandler;
|
|
365
|
+
connect(userId: string): Promise<void>;
|
|
366
|
+
disconnect(): Promise<void>;
|
|
367
|
+
reconnect(): Promise<void>;
|
|
368
|
+
send(message: Message): Promise<void>;
|
|
369
|
+
onMessage(handler: (message: Message) => void): void;
|
|
370
|
+
onConnectionStateChange(handler: (state: ConnectionState) => void): void;
|
|
371
|
+
onError(handler: (error: Error) => void): void;
|
|
372
|
+
getConnectionState(): ConnectionState;
|
|
373
|
+
isConnected(): boolean;
|
|
374
|
+
simulateReceive(message: Message): void;
|
|
375
|
+
simulateError(error: Error): void;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
declare class WebSocketClient implements TransportAdapter {
|
|
379
|
+
private ws;
|
|
380
|
+
private url;
|
|
381
|
+
private messageHandler;
|
|
382
|
+
private stateHandler;
|
|
383
|
+
private errorHandler;
|
|
384
|
+
private connectionState;
|
|
385
|
+
private reconnectAttempts;
|
|
386
|
+
private reconnectTimer;
|
|
387
|
+
private heartbeatTimer;
|
|
388
|
+
private currentUserId;
|
|
389
|
+
private shouldReconnect;
|
|
390
|
+
constructor(url: string);
|
|
391
|
+
connect(userId: string): Promise<void>;
|
|
392
|
+
private doConnect;
|
|
393
|
+
disconnect(): Promise<void>;
|
|
394
|
+
reconnect(): Promise<void>;
|
|
395
|
+
private scheduleReconnect;
|
|
396
|
+
private clearReconnectTimer;
|
|
397
|
+
private startHeartbeat;
|
|
398
|
+
private stopHeartbeat;
|
|
125
399
|
send(message: Message): Promise<void>;
|
|
126
|
-
onMessage(handler:
|
|
400
|
+
onMessage(handler: (message: Message) => void): void;
|
|
401
|
+
onConnectionStateChange(handler: (state: ConnectionState) => void): void;
|
|
402
|
+
onError(handler: (error: Error) => void): void;
|
|
403
|
+
getConnectionState(): ConnectionState;
|
|
404
|
+
isConnected(): boolean;
|
|
405
|
+
private updateState;
|
|
406
|
+
private handleError;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Base SDK Error class
|
|
411
|
+
*/
|
|
412
|
+
declare class SDKError extends Error {
|
|
413
|
+
readonly code: string;
|
|
414
|
+
readonly retryable: boolean;
|
|
415
|
+
readonly details?: Record<string, unknown> | undefined;
|
|
416
|
+
constructor(message: string, code: string, retryable?: boolean, details?: Record<string, unknown> | undefined);
|
|
417
|
+
toJSON(): {
|
|
418
|
+
name: string;
|
|
419
|
+
message: string;
|
|
420
|
+
code: string;
|
|
421
|
+
retryable: boolean;
|
|
422
|
+
details: Record<string, unknown> | undefined;
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Network-related errors (connection, timeout, etc.)
|
|
427
|
+
*/
|
|
428
|
+
declare class NetworkError extends SDKError {
|
|
429
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Encryption/Decryption errors
|
|
433
|
+
*/
|
|
434
|
+
declare class EncryptionError extends SDKError {
|
|
435
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Authentication/Authorization errors
|
|
439
|
+
*/
|
|
440
|
+
declare class AuthError extends SDKError {
|
|
441
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Validation errors (invalid input)
|
|
445
|
+
*/
|
|
446
|
+
declare class ValidationError extends SDKError {
|
|
447
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Storage-related errors
|
|
451
|
+
*/
|
|
452
|
+
declare class StorageError extends SDKError {
|
|
453
|
+
constructor(message: string, retryable?: boolean, details?: Record<string, unknown>);
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Session-related errors
|
|
457
|
+
*/
|
|
458
|
+
declare class SessionError extends SDKError {
|
|
459
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Transport-related errors
|
|
463
|
+
*/
|
|
464
|
+
declare class TransportError extends SDKError {
|
|
465
|
+
constructor(message: string, retryable?: boolean, details?: Record<string, unknown>);
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Configuration errors
|
|
469
|
+
*/
|
|
470
|
+
declare class ConfigError extends SDKError {
|
|
471
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Validate username format
|
|
476
|
+
*/
|
|
477
|
+
declare function validateUsername(username: string): void;
|
|
478
|
+
/**
|
|
479
|
+
* Validate message content
|
|
480
|
+
*/
|
|
481
|
+
declare function validateMessage(message: string): void;
|
|
482
|
+
/**
|
|
483
|
+
* Validate group name
|
|
484
|
+
*/
|
|
485
|
+
declare function validateGroupName(name: string): void;
|
|
486
|
+
/**
|
|
487
|
+
* Validate group members count
|
|
488
|
+
*/
|
|
489
|
+
declare function validateGroupMembers(memberCount: number): void;
|
|
490
|
+
/**
|
|
491
|
+
* Validate user ID format
|
|
492
|
+
*/
|
|
493
|
+
declare function validateUserId(userId: string): void;
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Convert File or Blob to base64 string
|
|
497
|
+
*/
|
|
498
|
+
declare function encodeFileToBase64(file: File | Blob): Promise<string>;
|
|
499
|
+
/**
|
|
500
|
+
* Convert base64 string to Blob
|
|
501
|
+
*/
|
|
502
|
+
declare function decodeBase64ToBlob(base64: string, mimeType: string): Blob;
|
|
503
|
+
/**
|
|
504
|
+
* Detect media type from MIME type
|
|
505
|
+
*/
|
|
506
|
+
declare function getMediaType(mimeType: string): MediaType;
|
|
507
|
+
/**
|
|
508
|
+
* Validate media file
|
|
509
|
+
*/
|
|
510
|
+
declare function validateMediaFile(file: File | Blob, filename?: string): void;
|
|
511
|
+
/**
|
|
512
|
+
* Create media metadata from file
|
|
513
|
+
*/
|
|
514
|
+
declare function createMediaMetadata(file: File | Blob, filename?: string): Promise<MediaMetadata>;
|
|
515
|
+
/**
|
|
516
|
+
* Create media attachment from file
|
|
517
|
+
*/
|
|
518
|
+
declare function createMediaAttachment(file: File | Blob, filename?: string): Promise<MediaAttachment>;
|
|
519
|
+
/**
|
|
520
|
+
* Format file size for display
|
|
521
|
+
*/
|
|
522
|
+
declare function formatFileSize(bytes: number): string;
|
|
523
|
+
|
|
524
|
+
declare class LocalStorageProvider implements StorageProvider {
|
|
525
|
+
readonly name = "local";
|
|
526
|
+
private storageDir;
|
|
527
|
+
constructor(storageDir?: string);
|
|
528
|
+
upload(data: string | Buffer, filename: string, mimeType: string): Promise<StorageUploadResult>;
|
|
529
|
+
download(storageKey: string): Promise<string>;
|
|
530
|
+
delete(storageKey: string): Promise<void>;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
interface S3Config {
|
|
534
|
+
region: string;
|
|
535
|
+
bucket: string;
|
|
536
|
+
credentials?: {
|
|
537
|
+
accessKeyId: string;
|
|
538
|
+
secretAccessKey: string;
|
|
539
|
+
};
|
|
540
|
+
endpoint?: string;
|
|
541
|
+
forcePathStyle?: boolean;
|
|
542
|
+
}
|
|
543
|
+
declare class S3StorageProvider implements StorageProvider {
|
|
544
|
+
readonly name = "s3";
|
|
545
|
+
private client;
|
|
546
|
+
private bucket;
|
|
547
|
+
constructor(config: S3Config);
|
|
548
|
+
upload(data: string | Buffer, filename: string, mimeType: string): Promise<StorageUploadResult>;
|
|
549
|
+
download(storageKey: string): Promise<string>;
|
|
550
|
+
delete(storageKey: string): Promise<void>;
|
|
127
551
|
}
|
|
128
552
|
|
|
129
553
|
interface ChatSDKConfig {
|
|
130
554
|
userStore: UserStoreAdapter;
|
|
131
555
|
messageStore: MessageStoreAdapter;
|
|
132
556
|
groupStore: GroupStoreAdapter;
|
|
557
|
+
storageProvider?: StorageProvider;
|
|
133
558
|
transport?: TransportAdapter;
|
|
559
|
+
logLevel?: LogLevel;
|
|
134
560
|
}
|
|
135
561
|
/**
|
|
136
562
|
* Main ChatSDK class - production-ready WhatsApp-style chat SDK
|
|
563
|
+
* Extends EventEmitter to provide event-driven architecture
|
|
564
|
+
*
|
|
565
|
+
* Events:
|
|
566
|
+
* - message:sent - Emitted when a message is sent
|
|
567
|
+
* - message:received - Emitted when a message is received
|
|
568
|
+
* - message:failed - Emitted when a message fails to send
|
|
569
|
+
* - connection:state - Emitted when connection state changes
|
|
570
|
+
* - session:created - Emitted when a session is created
|
|
571
|
+
* - group:created - Emitted when a group is created
|
|
572
|
+
* - user:created - Emitted when a user is created
|
|
573
|
+
* - error - Emitted when an error occurs
|
|
137
574
|
*/
|
|
138
|
-
declare class ChatSDK {
|
|
575
|
+
declare class ChatSDK extends EventEmitter {
|
|
139
576
|
private config;
|
|
140
577
|
private currentUser;
|
|
578
|
+
private messageQueue;
|
|
141
579
|
constructor(config: ChatSDKConfig);
|
|
580
|
+
private setupTransportHandlers;
|
|
581
|
+
private processMessageQueue;
|
|
142
582
|
/**
|
|
143
583
|
* Create a new user with generated identity keys
|
|
144
584
|
*/
|
|
@@ -150,7 +590,7 @@ declare class ChatSDK {
|
|
|
150
590
|
/**
|
|
151
591
|
* Set the current active user
|
|
152
592
|
*/
|
|
153
|
-
setCurrentUser(user: User): void
|
|
593
|
+
setCurrentUser(user: User): Promise<void>;
|
|
154
594
|
/**
|
|
155
595
|
* Get the current active user
|
|
156
596
|
*/
|
|
@@ -171,10 +611,21 @@ declare class ChatSDK {
|
|
|
171
611
|
* Send a message in a chat session (1:1 or group)
|
|
172
612
|
*/
|
|
173
613
|
sendMessage(session: ChatSession | GroupSession, plaintext: string): Promise<Message>;
|
|
614
|
+
/**
|
|
615
|
+
* Send a media message in a chat session (1:1 or group)
|
|
616
|
+
*/
|
|
617
|
+
sendMediaMessage(session: ChatSession | GroupSession, caption: string, media: MediaAttachment): Promise<Message>;
|
|
174
618
|
/**
|
|
175
619
|
* Decrypt a message
|
|
176
620
|
*/
|
|
177
621
|
decryptMessage(message: Message, user: User): Promise<string>;
|
|
622
|
+
/**
|
|
623
|
+
* Decrypt a media message
|
|
624
|
+
*/
|
|
625
|
+
decryptMediaMessage(message: Message, user: User): Promise<{
|
|
626
|
+
text: string;
|
|
627
|
+
media: MediaAttachment;
|
|
628
|
+
}>;
|
|
178
629
|
/**
|
|
179
630
|
* Get messages for a user
|
|
180
631
|
*/
|
|
@@ -183,6 +634,46 @@ declare class ChatSDK {
|
|
|
183
634
|
* Get messages for a group
|
|
184
635
|
*/
|
|
185
636
|
getMessagesForGroup(groupId: string): Promise<Message[]>;
|
|
637
|
+
/**
|
|
638
|
+
* Get the transport adapter
|
|
639
|
+
*/
|
|
640
|
+
getTransport(): TransportAdapter | undefined;
|
|
641
|
+
/**
|
|
642
|
+
* Get all users
|
|
643
|
+
*/
|
|
644
|
+
listUsers(): Promise<User[]>;
|
|
645
|
+
/**
|
|
646
|
+
* Get user by ID
|
|
647
|
+
*/
|
|
648
|
+
getUserById(userId: string): Promise<User | undefined>;
|
|
649
|
+
/**
|
|
650
|
+
* Get all groups
|
|
651
|
+
*/
|
|
652
|
+
listGroups(): Promise<Group[]>;
|
|
653
|
+
/**
|
|
654
|
+
* Get connection state
|
|
655
|
+
*/
|
|
656
|
+
getConnectionState(): ConnectionState;
|
|
657
|
+
/**
|
|
658
|
+
* Check if connected
|
|
659
|
+
*/
|
|
660
|
+
isConnected(): boolean;
|
|
661
|
+
/**
|
|
662
|
+
* Disconnect transport
|
|
663
|
+
*/
|
|
664
|
+
disconnect(): Promise<void>;
|
|
665
|
+
/**
|
|
666
|
+
* Reconnect transport
|
|
667
|
+
*/
|
|
668
|
+
reconnect(): Promise<void>;
|
|
669
|
+
/**
|
|
670
|
+
* Get message queue status
|
|
671
|
+
*/
|
|
672
|
+
getQueueStatus(): {
|
|
673
|
+
size: number;
|
|
674
|
+
pending: number;
|
|
675
|
+
retryable: number;
|
|
676
|
+
};
|
|
186
677
|
}
|
|
187
678
|
|
|
188
|
-
export { ChatSDK, type ChatSDKConfig, ChatSession, type Group, GroupSession, type GroupStoreAdapter, InMemoryGroupStore, InMemoryMessageStore, InMemoryTransport, InMemoryUserStore, type Message, type MessageStoreAdapter, type MessageType, type StoredUser, type TransportAdapter, type User, type UserStoreAdapter };
|
|
679
|
+
export { ALGORITHM, AuthError, CONNECTION_TIMEOUT, ChatSDK, type ChatSDKConfig, ChatSession, ConfigError, ConnectionState, EVENTS, EncryptionError, FILE_SIZE_LIMITS, GROUP_MAX_MEMBERS, GROUP_MIN_MEMBERS, GROUP_NAME_MAX_LENGTH, type Group, GroupSession, type GroupStoreAdapter, HEARTBEAT_INTERVAL, IV_LENGTH, InMemoryGroupStore, InMemoryMessageStore, InMemoryTransport, InMemoryUserStore, KEY_LENGTH, LocalStorageProvider, LogLevel, Logger, type LoggerConfig, MAX_QUEUE_SIZE, MESSAGE_MAX_LENGTH, MESSAGE_RETRY_ATTEMPTS, MESSAGE_RETRY_DELAY, type MediaAttachment, type MediaMetadata, MediaType, type Message, MessageStatus, type MessageStoreAdapter, type MessageType, NetworkError, PBKDF2_ITERATIONS, RECONNECT_BASE_DELAY, RECONNECT_MAX_ATTEMPTS, RECONNECT_MAX_DELAY, type S3Config, S3StorageProvider, SALT_LENGTH, SDKError, SUPPORTED_CURVE, SUPPORTED_MIME_TYPES, SessionError, StorageError, type StorageProvider, type StorageUploadResult, type StoredUser, TAG_LENGTH, type TransportAdapter, TransportError, USERNAME_MAX_LENGTH, USERNAME_MIN_LENGTH, type User, type UserStoreAdapter, ValidationError, WebSocketClient, createMediaAttachment, createMediaMetadata, decodeBase64ToBlob, encodeFileToBase64, formatFileSize, getMediaType, logger, validateGroupMembers, validateGroupName, validateMediaFile, validateMessage, validateUserId, validateUsername };
|