@quickly-desk/sdk
v0.0.5
Published
SDK for easy integration of Quickly Desk in React and React Native applications
Maintainers
Readme
Quickly Desk SDK
SDK for easy integration of Quickly Desk in React and React Native applications.
Installation
npm install @quickly-desk/sdk
# or
yarn add @quickly-desk/sdkUsage
React (Web)
import React, { useMemo } from "react";
import {
QuicklyDeskProvider,
useCustomerAuth,
useChatsWithWebSocket,
} from "@quickly-desk/sdk";
function App() {
const config = useMemo(
() => ({
publicKey: "your-public-key",
customerReference: "unique-customer-id",
customerName: "Customer Name",
phone: "11999999999", // optional
email: "[email protected]", // optional
avatar: "https://example.com/avatar.png", // optional
metadata: {
// Other optional metadata such as device, IP address, country...
},
}),
[],
);
return (
<QuicklyDeskProvider config={config}>
<YourApp />
</QuicklyDeskProvider>
);
}function YourApp() { const { loading, error, signOut } = useCustomerAuth(); const { chats, messages, sendMessage, createChat } = useChatsWithWebSocket();
// Use the hooks as needed return ...; }
### React Native
```tsx
import React, { useMemo } from "react";
import {
QuicklyDeskProvider,
useCustomerAuth,
useChatsWithWebSocket,
} from "@quickly-desk/sdk";
function App() {
const config = useMemo(
() => ({
publicKey: "your-public-key",
customerReference: "unique-customer-id",
customerName: "Customer Name",
phone: "11999999999",
email: "[email protected]",
}),
[]
);
return (
<QuicklyDeskProvider config={config}>
<YourApp />
</QuicklyDeskProvider>
);
}Features
- No caching: The SDK always authenticates when the provider is executed
- Automatic token refresh: Tokens are automatically refreshed when expired
- Request queue: Failed requests are queued and retried after token refresh
- WebSocket support: Real-time chat functionality with WebSocket connections
API
Hooks
useCustomerAuth()
Hook for managing customer authentication.
const { loading, error, signOut } = useCustomerAuth();loading: Loading state during authentication (boolean)error: Error message if authentication fails (string | null)signOut(): Function to sign out manually
useChatsWithWebSocket()
Main hook for managing chats and messages. Automatically manages the WebSocket connection based on the component lifecycle.
Features:
- ✅ Automatically connects to WebSocket when the component mounts
- ✅ Waits for the WebSocket connection to be ready before loading chats
- ✅ Automatically calls
loadChats()after connecting - ✅ Automatically disconnects when the component unmounts (if it's the last component using it)
- ✅ Uses reference counting to keep the connection alive during screen navigation
- ✅ Protection against race conditions and multiple calls
- ✅ Robust error and timeout handling
- ✅ Can be used in multiple components simultaneously
const {
chats,
currentChat,
messages,
staffPresence,
typingStatus,
ws,
loading,
sendMessageLoading,
createChatLoading,
loadChats,
loadChatHistory,
sendMessage,
createChat,
} = useChatsWithWebSocket();Returned properties:
chats: List of chats (Chat[])currentChat: Currently selected chat (Chat | null)messages: Messages of the current chat (ChatMessage[])staffPresence: Staff members currently viewing chats (string[], each entry is"staffId:chatId")typingStatus: Typing status per chat ({ [id_chat: string]: { [id_user: string]: string } })ws: WebSocket connection (WebSocket | null)loading: Loading state (boolean)sendMessageLoading: Message sending state (boolean)createChatLoading: Chat creation state (boolean)loadChats(): Loads the chat listloadChatHistory(id_chat): Loads a specific chat's historysendMessage(id_chat, content): Sends a messagecreateChat(): Creates a new chatmarkAsRead(id_chat): Marks all messages in the chat as read for the customer (zeroesunread_count)
Usage examples:
// Chat list screen
function ChatsListScreen() {
const { chats, loading, loadChats, createChat } = useChatsWithWebSocket();
// WebSocket connects automatically on mount
// loadChats() is called automatically after connection
// WebSocket disconnects automatically on unmount
const onRefresh = async () => {
await loadChats(); // Can be called manually for refresh
};
return (
<FlatList
data={chats}
renderItem={({ item }) => <ChatListItem chat={item} />}
onRefresh={onRefresh}
refreshing={loading}
/>
);
}
// Individual chat screen
function ChatScreen({ id_chat }: { id_chat: string }) {
const { messages, loadChatHistory, sendMessage, loading } =
useChatsWithWebSocket();
// Can use the same hook - WebSocket connection is shared
// No need to manage the connection manually
useEffect(() => {
if (id_chat) {
loadChatHistory(id_chat);
}
}, [id_chat, loadChatHistory]);
return (
<View>
<FlatList
data={messages}
renderItem={({ item }) => <MessageBubble message={item} />}
/>
<MessageInput onSend={(content) => sendMessage(id_chat, content)} />
</View>
);
}Types
interface Chat {
id_chat: string;
id_tenant: string;
id_customer: string;
created_at?: string;
updated_at?: string;
customer_name?: string;
last_message?: string | null;
last_message_time?: string | null;
unread_count?: number;
}
interface ChatMessage {
id_chat_message: number;
id_chat: string;
sender: string;
id_sender: string;
read: boolean;
content: string;
created_at?: string;
}Configuration
SDKConfig
interface SDKConfig {
publicKey: string; // Public key (required)
customerReference: string; // Unique customer ID (required)
customerName: string; // Customer name (required)
phone?: string; // Customer phone (optional)
email?: string; // Customer email (optional)
avatar?: string; // Customer avatar URL (optional)
metadata?: Record<string, any>; // Additional customer metadata (optional)
apiUrl?: string; // API URL (optional, overrides build default)
wsUrl?: string; // WebSocket URL (optional, overrides build default)
}Authentication Flow
The SDK automatically:
- Authenticates when the provider is executed (calls
/auth/customer) - Stores the token in memory (no persistent storage)
- Refreshes the token automatically when it expires
- Queues failed requests during token refresh and retries them after refresh
Edge Cases and Behaviors
Limits and Validations
- Maximum message size: 1000 characters
- Maximum request queue size: 50 requests
- Queue timeout: 30 seconds
- WebSocket connection timeout: 10 seconds (default)
- Maximum WebSocket retry attempts: 3 attempts
- Maximum processed messages in memory: 100 IDs
Automatic Behaviors
- WebSocket reconnection: The SDK automatically reconnects if the connection closes unexpectedly (code !== 1000)
- Duplicate prevention: Duplicate messages are automatically ignored using a Set of processed IDs
- Message validation: All WebSocket messages are validated before being processed
- Automatic retry: WebSocket attempts to reconnect up to 3 times with exponential backoff (1s, 2s, 4s, max 10s)
- Resource cleanup: All timeouts and listeners are properly cleaned up when components unmount
Error Handling
The SDK classifies errors into specific types:
NetworkError: Network connection errorsTimeoutError: Request or connection timeoutsAuthenticationError: Authentication errorsValidationError: Input validation errors
Multiple Components
You can use useChatsWithWebSocket in multiple components simultaneously:
- The WebSocket connection is shared between all components
- A reference counter manages when to connect/disconnect
- The connection only closes when the last component unsubscribes
Screen Navigation
- When navigating from the chat list to a specific chat, the WebSocket connection is kept alive
- When leaving the list screen, the connection closes automatically
- Messages keep arriving even when not on the list screen (if another component is using it)
Troubleshooting
For common problems and solutions, see TROUBLESHOOTING.md.
License
MIT
