@enfin/chat 1.2.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.
Files changed (73) hide show
  1. package/README.md +224 -0
  2. package/dist/assets/music/i_phone_message.mp3 +0 -0
  3. package/dist/call/WebRTCManager.d.ts +54 -0
  4. package/dist/call/WebRTCManager.js +274 -0
  5. package/dist/call/signaling.d.ts +3 -0
  6. package/dist/call/signaling.js +24 -0
  7. package/dist/call/types.d.ts +25 -0
  8. package/dist/call/types.js +13 -0
  9. package/dist/components/Chat.d.ts +14 -0
  10. package/dist/components/Chat.js +452 -0
  11. package/dist/components/index.d.ts +3 -0
  12. package/dist/components/index.js +2 -0
  13. package/dist/context/ChatContext.d.ts +59 -0
  14. package/dist/context/ChatContext.js +647 -0
  15. package/dist/esm/call/WebRTCManager.d.ts +54 -0
  16. package/dist/esm/call/WebRTCManager.js +274 -0
  17. package/dist/esm/call/signaling.d.ts +3 -0
  18. package/dist/esm/call/signaling.js +24 -0
  19. package/dist/esm/call/types.d.ts +25 -0
  20. package/dist/esm/call/types.js +13 -0
  21. package/dist/esm/components/Chat.d.ts +14 -0
  22. package/dist/esm/components/Chat.js +452 -0
  23. package/dist/esm/components/index.d.ts +3 -0
  24. package/dist/esm/components/index.js +2 -0
  25. package/dist/esm/context/ChatContext.d.ts +59 -0
  26. package/dist/esm/context/ChatContext.js +647 -0
  27. package/dist/esm/hooks/index.d.ts +6 -0
  28. package/dist/esm/hooks/index.js +6 -0
  29. package/dist/esm/hooks/useCall.d.ts +15 -0
  30. package/dist/esm/hooks/useCall.js +38 -0
  31. package/dist/esm/hooks/useChat.d.ts +23 -0
  32. package/dist/esm/hooks/useChat.js +40 -0
  33. package/dist/esm/hooks/useMessages.d.ts +17 -0
  34. package/dist/esm/hooks/useMessages.js +38 -0
  35. package/dist/esm/hooks/usePresence.d.ts +4 -0
  36. package/dist/esm/hooks/usePresence.js +12 -0
  37. package/dist/esm/hooks/useRooms.d.ts +9 -0
  38. package/dist/esm/hooks/useRooms.js +19 -0
  39. package/dist/esm/hooks/useSocket.d.ts +7 -0
  40. package/dist/esm/hooks/useSocket.js +92 -0
  41. package/dist/esm/index.d.ts +11 -0
  42. package/dist/esm/index.js +15 -0
  43. package/dist/esm/utils/index.d.ts +2 -0
  44. package/dist/esm/utils/index.js +2 -0
  45. package/dist/esm/utils/ringtone.d.ts +2 -0
  46. package/dist/esm/utils/ringtone.js +39 -0
  47. package/dist/esm/utils/testUtils.d.ts +102 -0
  48. package/dist/esm/utils/testUtils.js +153 -0
  49. package/dist/hooks/index.d.ts +6 -0
  50. package/dist/hooks/index.js +6 -0
  51. package/dist/hooks/useCall.d.ts +15 -0
  52. package/dist/hooks/useCall.js +38 -0
  53. package/dist/hooks/useChat.d.ts +23 -0
  54. package/dist/hooks/useChat.js +40 -0
  55. package/dist/hooks/useMessages.d.ts +17 -0
  56. package/dist/hooks/useMessages.js +38 -0
  57. package/dist/hooks/usePresence.d.ts +4 -0
  58. package/dist/hooks/usePresence.js +12 -0
  59. package/dist/hooks/useRooms.d.ts +9 -0
  60. package/dist/hooks/useRooms.js +19 -0
  61. package/dist/hooks/useSocket.d.ts +7 -0
  62. package/dist/hooks/useSocket.js +92 -0
  63. package/dist/index.d.ts +11 -0
  64. package/dist/index.js +15 -0
  65. package/dist/public/music/i_phone_message.mp3 +0 -0
  66. package/dist/style.css +1226 -0
  67. package/dist/utils/index.d.ts +2 -0
  68. package/dist/utils/index.js +2 -0
  69. package/dist/utils/ringtone.d.ts +2 -0
  70. package/dist/utils/ringtone.js +39 -0
  71. package/dist/utils/testUtils.d.ts +102 -0
  72. package/dist/utils/testUtils.js +153 -0
  73. package/package.json +44 -0
@@ -0,0 +1,2 @@
1
+ export * from './testUtils';
2
+ export * from './ringtone';
@@ -0,0 +1,2 @@
1
+ export * from './testUtils';
2
+ export * from './ringtone';
@@ -0,0 +1,2 @@
1
+ export declare function startRingtone(url?: string): void;
2
+ export declare function stopRingtone(): void;
@@ -0,0 +1,39 @@
1
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
2
+ import defaultRingtoneUrl from '../assets/music/i_phone_message.mp3';
3
+ let audioEl = null;
4
+ let currentUrl = null;
5
+ function getAudio(url) {
6
+ const target = url || defaultRingtoneUrl;
7
+ if (!audioEl || currentUrl !== target) {
8
+ if (audioEl) {
9
+ audioEl.pause();
10
+ audioEl.src = '';
11
+ }
12
+ audioEl = new Audio(target);
13
+ audioEl.loop = true;
14
+ audioEl.preload = 'auto';
15
+ currentUrl = target;
16
+ }
17
+ return audioEl;
18
+ }
19
+ export function startRingtone(url) {
20
+ try {
21
+ const audio = getAudio(url);
22
+ audio.currentTime = 0;
23
+ const playPromise = audio.play();
24
+ if (playPromise && typeof playPromise.catch === 'function') {
25
+ playPromise.catch((err) => {
26
+ console.log('[RINGTONE] play() rejected:', err?.message || err);
27
+ });
28
+ }
29
+ }
30
+ catch (err) {
31
+ console.log('[RINGTONE] start failed:', err?.message || err);
32
+ }
33
+ }
34
+ export function stopRingtone() {
35
+ if (!audioEl)
36
+ return;
37
+ audioEl.pause();
38
+ audioEl.currentTime = 0;
39
+ }
@@ -0,0 +1,102 @@
1
+ import { Socket } from 'socket.io-client';
2
+ /**
3
+ * Test utilities for developers to create test users and simulate interactions
4
+ *
5
+ * This utility allows developers to:
6
+ * 1. Create multiple test users that can chat with each other
7
+ * 2. Send messages between test users
8
+ * 3. Make audio calls between test users
9
+ * 4. Test custom socket events
10
+ */
11
+ export interface TestUser {
12
+ id: string;
13
+ name: string;
14
+ socket: Socket;
15
+ rooms: string[];
16
+ }
17
+ /**
18
+ * Create a test user with automatic socket connection
19
+ *
20
+ * @param serverUrl - Chat server URL
21
+ * @param userId - User ID (optional, generated if not provided)
22
+ * @param userName - User name
23
+ * @returns Test user object with socket connection
24
+ */
25
+ export declare function createTestUser(serverUrl: string, userName: string, userId?: string): TestUser;
26
+ /**
27
+ * Create multiple test users for testing
28
+ *
29
+ * @param serverUrl - Chat server URL
30
+ * @param userNames - Array of user names
31
+ * @returns Array of test users
32
+ */
33
+ export declare function createTestUsers(serverUrl: string, userNames: string[]): TestUser[];
34
+ /**
35
+ * Create a test room between users
36
+ *
37
+ * @param users - Users to add to the room
38
+ * @param roomName - Room name
39
+ * @param isDirect - Whether this is a direct chat
40
+ * @returns Promise resolving to the created room
41
+ */
42
+ export declare function createTestRoom(users: TestUser[], roomName: string, isDirect?: boolean): Promise<any>;
43
+ /**
44
+ * Send a message from one user to another
45
+ *
46
+ * @param from - Sending user
47
+ * @param roomId - Room ID
48
+ * @param content - Message content
49
+ * @returns Promise resolving when message is sent
50
+ */
51
+ export declare function sendMessage(from: TestUser, roomId: string, content: string): Promise<any>;
52
+ /**
53
+ * Start an audio call
54
+ *
55
+ * @param from - Initiating user
56
+ * @param to - Target user
57
+ * @param roomId - Room ID
58
+ * @returns Promise resolving when call is initiated
59
+ */
60
+ export declare function startCall(from: TestUser, to: TestUser, roomId: string): Promise<any>;
61
+ /**
62
+ * Accept an incoming call
63
+ *
64
+ * @param to - User accepting call
65
+ * @param callId - Call ID
66
+ * @returns Promise resolving when call is accepted
67
+ */
68
+ export declare function acceptCall(to: TestUser, callId: string): Promise<any>;
69
+ /**
70
+ * End a call
71
+ *
72
+ * @param by - User ending call
73
+ * @param callId - Call ID
74
+ * @returns Promise resolving when call is ended
75
+ */
76
+ export declare function endCall(by: TestUser, callId: string): Promise<any>;
77
+ /**
78
+ * Listen for socket events (useful for testing)
79
+ *
80
+ * @param socket - Socket to listen on
81
+ * @param event - Event name
82
+ * @param callback - Callback function
83
+ * @returns Cleanup function to remove listener
84
+ */
85
+ export declare function onSocketEvent(socket: Socket, event: string, callback: (data: any) => void): () => void;
86
+ /**
87
+ * Listen to custom socket events (exposed by ChatProvider)
88
+ *
89
+ * @param eventName - Event name to listen to
90
+ * @param callback - Callback function
91
+ * @returns Cleanup function
92
+ */
93
+ export declare function onCustomSocketEvent(eventName: string, callback: (data: any) => void): () => void;
94
+ /**
95
+ * Emit custom event through the socket
96
+ *
97
+ * @param user - User to emit from
98
+ * @param event - Event name
99
+ * @param data - Event data
100
+ * @returns Promise resolving when event is sent
101
+ */
102
+ export declare function emitCustomEvent(user: TestUser, event: string, data?: any): Promise<any>;
@@ -0,0 +1,153 @@
1
+ import io from 'socket.io-client';
2
+ /**
3
+ * Create a test user with automatic socket connection
4
+ *
5
+ * @param serverUrl - Chat server URL
6
+ * @param userId - User ID (optional, generated if not provided)
7
+ * @param userName - User name
8
+ * @returns Test user object with socket connection
9
+ */
10
+ export function createTestUser(serverUrl, userName, userId) {
11
+ const id = userId || `user_${Math.random().toString(36).substr(2, 9)}`;
12
+ const socket = io(`${serverUrl}/chat`, {
13
+ auth: { userId: id, userName, tenantId: id },
14
+ transports: ['websocket'],
15
+ });
16
+ return {
17
+ id,
18
+ name: userName,
19
+ socket,
20
+ rooms: [],
21
+ };
22
+ }
23
+ /**
24
+ * Create multiple test users for testing
25
+ *
26
+ * @param serverUrl - Chat server URL
27
+ * @param userNames - Array of user names
28
+ * @returns Array of test users
29
+ */
30
+ export function createTestUsers(serverUrl, userNames) {
31
+ return userNames.map((name, index) => {
32
+ const userId = `test_user_${String(index + 1).padStart(2, '0')}`;
33
+ return createTestUser(serverUrl, name, userId);
34
+ });
35
+ }
36
+ /**
37
+ * Create a test room between users
38
+ *
39
+ * @param users - Users to add to the room
40
+ * @param roomName - Room name
41
+ * @param isDirect - Whether this is a direct chat
42
+ * @returns Promise resolving to the created room
43
+ */
44
+ export async function createTestRoom(users, roomName, isDirect = false) {
45
+ const roomId = `room_${Date.now()}`;
46
+ if (isDirect && users.length !== 2) {
47
+ throw new Error('Direct rooms require exactly 2 users');
48
+ }
49
+ // Create room (first user creates it)
50
+ await users[0].socket.emitWithAck('room:create', {
51
+ name: roomName,
52
+ type: isDirect ? 'direct' : 'group',
53
+ members: users.map(u => u.id),
54
+ });
55
+ // Wait a bit for room to propagate
56
+ await new Promise(resolve => setTimeout(resolve, 100));
57
+ // Join all users to the room
58
+ for (const user of users) {
59
+ await user.socket.emitWithAck('join', { roomId: roomId });
60
+ user.rooms.push(roomId);
61
+ }
62
+ return { id: roomId, name: roomName, type: isDirect ? 'direct' : 'group' };
63
+ }
64
+ /**
65
+ * Send a message from one user to another
66
+ *
67
+ * @param from - Sending user
68
+ * @param roomId - Room ID
69
+ * @param content - Message content
70
+ * @returns Promise resolving when message is sent
71
+ */
72
+ export async function sendMessage(from, roomId, content) {
73
+ return from.socket.emitWithAck('message:send', {
74
+ roomId,
75
+ content,
76
+ });
77
+ }
78
+ /**
79
+ * Start an audio call
80
+ *
81
+ * @param from - Initiating user
82
+ * @param to - Target user
83
+ * @param roomId - Room ID
84
+ * @returns Promise resolving when call is initiated
85
+ */
86
+ export async function startCall(from, to, roomId) {
87
+ return from.socket.emitWithAck('call:initiate', {
88
+ roomId,
89
+ participantId: to.id,
90
+ });
91
+ }
92
+ /**
93
+ * Accept an incoming call
94
+ *
95
+ * @param to - User accepting call
96
+ * @param callId - Call ID
97
+ * @returns Promise resolving when call is accepted
98
+ */
99
+ export async function acceptCall(to, callId) {
100
+ return to.socket.emitWithAck('call:accept', { callId });
101
+ }
102
+ /**
103
+ * End a call
104
+ *
105
+ * @param by - User ending call
106
+ * @param callId - Call ID
107
+ * @returns Promise resolving when call is ended
108
+ */
109
+ export async function endCall(by, callId) {
110
+ return by.socket.emitWithAck('call:end', { callId });
111
+ }
112
+ /**
113
+ * Listen for socket events (useful for testing)
114
+ *
115
+ * @param socket - Socket to listen on
116
+ * @param event - Event name
117
+ * @param callback - Callback function
118
+ * @returns Cleanup function to remove listener
119
+ */
120
+ export function onSocketEvent(socket, event, callback) {
121
+ socket.on(event, callback);
122
+ return () => socket.off(event, callback);
123
+ }
124
+ /**
125
+ * Listen to custom socket events (exposed by ChatProvider)
126
+ *
127
+ * @param eventName - Event name to listen to
128
+ * @param callback - Callback function
129
+ * @returns Cleanup function
130
+ */
131
+ export function onCustomSocketEvent(eventName, callback) {
132
+ const handler = (event) => {
133
+ if (event.detail.event === eventName) {
134
+ callback(event.detail.data);
135
+ }
136
+ };
137
+ window.addEventListener('chat:socket-event', handler);
138
+ return () => window.removeEventListener('chat:socket-event', handler);
139
+ }
140
+ /**
141
+ * Emit custom event through the socket
142
+ *
143
+ * @param user - User to emit from
144
+ * @param event - Event name
145
+ * @param data - Event data
146
+ * @returns Promise resolving when event is sent
147
+ */
148
+ export function emitCustomEvent(user, event, data) {
149
+ if (user.socket.connected) {
150
+ return user.socket.emitWithAck(event, data);
151
+ }
152
+ return Promise.reject('Socket not connected');
153
+ }
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@enfin/chat",
3
+ "version": "1.2.0",
4
+ "description": "React frontend SDK for chat platform",
5
+ "main": "dist/index.js",
6
+ "module": "dist/esm/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.js"
13
+ },
14
+ "./styles.css": "./dist/style.css"
15
+ },
16
+ "scripts": {
17
+ "build": "tsc -p tsconfig.json && tsc -p tsconfig.json --module esnext --outDir dist/esm && node -e \"const fs=require('fs');fs.copyFileSync('src/styles.css','dist/style.css');fs.cpSync('public','dist/public',{recursive:true});fs.cpSync('src/assets','dist/assets',{recursive:true});\"",
18
+ "prepublishOnly": "npm run build",
19
+ "dev": "tsc --watch",
20
+ "test": "jest"
21
+ },
22
+ "peerDependencies": {
23
+ "react": "^18.0.0",
24
+ "react-dom": "^18.0.0",
25
+ "socket.io-client": "^4.6.0"
26
+ },
27
+ "dependencies": {
28
+ "@enfin/chat-shared": "^1.0.0",
29
+ "socket.io-client": "^4.6.0"
30
+ },
31
+ "devDependencies": {
32
+ "@types/react": "^18.0.0",
33
+ "@types/react-dom": "^18.0.0",
34
+ "typescript": "^5.0.0"
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "README.md"
39
+ ],
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "style": "src/styles.css"
44
+ }