@emd-cloud/react-components
v1.14.5
Published
Use the EMD Cloud components with one package
Readme
EMD Cloud / React Components
Overview
The EMD Cloud React components provide a set of React components for interacting with the EMD Cloud platform. These components are designed to simplify working with EMD Cloud services in your React applications.
Getting Started
Register on the EMD Cloud platform and create an application at https://console.cloud.emd.one.
Obtain your application's API token.
Install the required packages:
NPM
# Install the React components npm install @emd-cloud/react-components # Install the required peer dependencies (v1.11.0+ required for chat features) npm install @emd-cloud/sdkFor TypeScript projects, types are included automatically. No additional @types packages needed.
Wrap your application with the ApplicationProvider:
import { ApplicationProvider } from '@emd-cloud/react-components'; function App() { return ( <ApplicationProvider app="your-app-id" apiUrl="https://api.emd.one" // optional, defaults to this value authToken="your-auth-token" // optional, can be set later > {/* Your app components */} </ApplicationProvider> ); }
That's it! The EMD Cloud React components are now ready to use.
TypeScript Support
This library provides full TypeScript support with exported types from the EMD Cloud SDK. You can import and use these types in your TypeScript applications:
import {
UserData,
AccountStatus,
PingStatus,
SocialProvider,
AppEnvironment,
ForgotPassData,
ForgotPassCheckCodeData,
OAuthUrlResponse
} from '@emd-cloud/react-components';
// Use the types in your components
interface UserProfileProps {
user: UserData;
onStatusChange: (status: AccountStatus) => void;
}
const UserProfile: React.FC<UserProfileProps> = ({ user, onStatusChange }) => {
return (
<div>
<h3>{user.firstName} {user.lastName}</h3>
<p>Status: {user.accountStatus}</p>
<p>Online: {user.pingStatus === PingStatus.Online ? 'Yes' : 'No'}</p>
</div>
);
};Available Types:
Authentication Types:
UserData- Complete user information interfaceAccountStatus- User account status enum (Pending,Approved,Rejected)PingStatus- User online status enum (Online,Offline)SocialProvider- OAuth provider enum (VK,YANDEX)AppEnvironment- Application environment enum (Client,Server)ForgotPassData- Password recovery request dataForgotPassCheckCodeData- Password recovery code verification dataOAuthUrlResponse- OAuth URL response interface
Database Types:
Database- Database instance interfaceDatabaseRowData- Generic database row data structureDatabaseQuery- MongoDB-style query object for filteringDatabaseSort- Sorting configuration for database queriesDatabaseListOptions- Options for listing/querying database rowsDatabaseGetRowOptions- Options for retrieving a single rowDatabaseCountOptions- Options for counting rowsDatabaseCreateOptions- Options for creating new rowsDatabaseUpdateOptions- Options for updating existing rowsDatabaseBulkUpdatePayload- Bulk update operation payloadDatabaseRowResponse- Single row response formatDatabaseRowsResponse- Multiple rows response formatDatabaseCountResponse- Row count response formatDatabaseBulkResponse- Bulk operation response formatDatabaseDeleteResponse- Delete operation response formatDatabaseTriggerResponse- Button trigger response formatDatabaseSaveMode- Save mode enum for database operations
Chat Types:
ChatChannelType- Chat channel type enum (Public,StaffToUser,PeerToPeer,Staff)ChatReadPermission- Read permission levels for channelsChatWritePermission- Write permission levels for channelsChatChannel- Chat channel data structureChatMessage- Chat message structureChatAttachment- Message attachment structure (images, files)ChatListOptions- Options for listing channelsChatMessageListOptions- Options for listing messagesSendMessageOptions- Options for sending messagesGetUnreadCountOptions- Options for getting unread countsUnreadCountResponse- Unread message count responseConnectionState- WebSocket connection state enum (Connecting,Connected,Disconnected,Error)WebSocketEvent- WebSocket event types enumChatWebSocketOptions- WebSocket configuration optionsChatWebSocketCallbacks- Event handler callbacks for real-time events
Common Types:
CallOptions- API call configuration optionsAuthType- Authentication type enum (auth-token,api-token)
Components
ApplicationProvider
Description:
The ApplicationProvider is the foundational component that wraps your React application to enable EMD Cloud functionality. It automatically initializes and manages the EMD Cloud SDK instance, providing context to all child components and hooks. This provider handles SDK initialization, token management, and maintains the connection to EMD Cloud services.
Props:
app(string, required): Your EMD Cloud application ID obtained from the consoleapiUrl(string, optional): EMD Cloud API endpoint URL. Defaults to"https://api.emd.one"authToken(string, optional): Initial authentication token. Can be set later via hookstokenType(string, optional): Authentication token type for API requests. Defaults to"token"children(ReactNode, required): Your application components
Key Features:
- Automatic SDK Management: Initializes EMD Cloud SDK on mount and manages its lifecycle
- Dynamic Loading: Gracefully handles cases where SDK is not installed
- Token Management: Maintains authentication state across the application
- Context Provision: Provides SDK instance and user data to all child components
- Error Handling: Fails gracefully with helpful warnings when SDK is unavailable
Example:
import { ApplicationProvider } from '@emd-cloud/react-components';
function App() {
return (
<ApplicationProvider
app="your-app-id"
apiUrl="https://api.emd.one" // optional, defaults to this value
authToken="your-auth-token" // optional, can be set later via useAuth
tokenType="token" // optional, defaults to "token"
>
<YourAppComponents />
</ApplicationProvider>
);
}
// With environment variables
function App() {
return (
<ApplicationProvider
app={process.env.REACT_APP_EMD_CLOUD_APP_ID}
authToken={localStorage.getItem('emd_auth_token')}
>
<YourAppComponents />
</ApplicationProvider>
);
}Important Notes:
- The ApplicationProvider must wrap any components that use EMD Cloud hooks
- The SDK instance is available after the component mounts (handles async initialization)
- All authentication and user management flows depend on this provider being properly configured
- If the SDK peer dependency is not installed, the provider will log a warning and continue without SDK functionality
Hooks
Authorization Hooks:
Hook: useAuth
Description:
This hook manages user authentication processes through the EMD Cloud platform using the EMD Cloud SDK. It provides methods for login, registration, logout, social authentication, and password recovery. The hook automatically manages user state and integrates with the SDK for secure authentication.
Available Methods:
logInUser(function): Log in a user with email/password.signUpUser(function): Register a new user.authorization(function): Check authentication status using a token.socialLogin(function): Initiate OAuth login with VK or Yandex.exchangeOAuthToken(function): Complete OAuth flow by exchanging secret for token.forgotPassword(function): Initiate password recovery process.forgotPasswordCheckCode(function): Verify password reset code.forgotPasswordChange(function): Complete password reset.updateUser(function): Update current or specified user’s profile information.logOutUser(function): Log out the current user.
Return Value: Returns an object with:
userInfo(object): Current user information.authorization(function): For authentication verification.logInUser(function): For email/password login.signUpUser(function): For user registration.socialLogin(function): For OAuth authentication.exchangeOAuthToken(function): For completing OAuth flow.forgotPassword(function): For initiating password recovery.forgotPasswordCheckCode(function): For verifying reset codes.forgotPasswordChange(function): For completing password reset.updateUser(function): Update current or specified user’s profile information.logOutUser(function): For logout.
Basic Authentication Example:
import { useAuth } from '@emd-cloud/react-components';
const MyAuthComponent = () => {
const { logInUser, signUpUser, logOutUser, userInfo } = useAuth();
const handleLogin = async (login, password) => {
try {
const user = await logInUser({ login, password });
console.log('Logged in user:', user);
} catch (error) {
console.error('Login failed:', error);
}
};
const handleSignUp = async (login, password) => {
try {
const newUser = await signUpUser({
login,
password,
firstName: 'John',
lastName: 'Doe',
captchaToken: 'your-captcha-token' // optional
});
console.log('Registered user:', newUser);
} catch (error) {
console.error('Registration failed:', error);
}
};
const handleLogout = () => {
logOutUser();
console.log('User logged out.');
};
return (
<div>
<h3>Current User: {userInfo ? userInfo.login : 'Not logged in'}</h3>
{/* Implement your login and signup forms here */}
<button onClick={() => handleLogin('[email protected]', 'password123')}>Login</button>
<button onClick={() => handleSignUp('[email protected]', 'password123')}>Sign Up</button>
<button onClick={handleLogout}>Logout</button>
</div>
);
};Social Login Example:
import { useAuth } from '@emd-cloud/react-components';
const SocialLoginComponent = () => {
const { socialLogin, exchangeOAuthToken } = useAuth();
const handleVKLogin = async () => {
try {
const response = await socialLogin({
provider: 'vk',
redirectUrl: 'https://myapp.com/auth/callback'
});
// Redirect user to VK for authentication
window.location.href = response.url;
} catch (error) {
console.error('Social login failed:', error);
}
};
const handleYandexLogin = async () => {
try {
const response = await socialLogin({
provider: 'yandex',
redirectUrl: 'https://myapp.com/auth/callback'
});
// Redirect user to Yandex for authentication
window.location.href = response.url;
} catch (error) {
console.error('Social login failed:', error);
}
};
// Handle OAuth callback (call this on your callback page)
const handleOAuthCallback = async () => {
const urlParams = new URLSearchParams(window.location.search);
const secret = urlParams.get('secret');
if (secret) {
try {
const userData = await exchangeOAuthToken(secret);
console.log('User authenticated:', userData);
// Redirect to dashboard or main page
} catch (error) {
console.error('OAuth token exchange failed:', error);
}
}
};
return (
<div>
<button onClick={handleVKLogin}>Login with VK</button>
<button onClick={handleYandexLogin}>Login with Yandex</button>
</div>
);
};Password Recovery Example:
import { useAuth } from '@emd-cloud/react-components';
const PasswordRecoveryComponent = () => {
const { forgotPassword, forgotPasswordCheckCode, forgotPasswordChange } = useAuth();
const handleForgotPassword = async (email) => {
try {
const response = await forgotPassword({ email });
console.log('Password reset requested:', response.requestId);
// Save requestId for next steps
} catch (error) {
console.error('Password reset request failed:', error);
}
};
const handleCheckCode = async (requestId, code) => {
try {
const response = await forgotPasswordCheckCode({ requestId, code });
console.log('Code verified:', response);
} catch (error) {
console.error('Code verification failed:', error);
}
};
const handleChangePassword = async (requestId, newPassword, newPasswordRepeat) => {
try {
const userData = await forgotPasswordChange({
requestId,
newPassword,
newPasswordRepeat
});
console.log('Password changed successfully:', userData);
} catch (error) {
console.error('Password change failed:', error);
}
};
// Implementation details for your forms...
};Database Hooks:
Hook: useDatabase
Description:
The useDatabase hook provides comprehensive database operations for EMD Cloud collections using the EMD Cloud SDK. It offers type-safe CRUD operations, advanced querying with MongoDB-style syntax, sorting, pagination, and bulk operations. This hook automatically manages authentication and provides error handling for all database interactions.
Available Methods:
getRows<T>(function): Retrieve multiple rows with filtering, sorting, and paginationcountRows(function): Count rows matching specific criteriagetRow<T>(function): Retrieve a single row by IDcreateRow<T>(function): Create a new row in the collectionupdateRow<T>(function): Update an existing row by IDbulkUpdate(function): Perform bulk updates on multiple rowsdeleteRow(function): Delete a single row by IDdeleteRows(function): Delete multiple rows matching criteriatriggerButton(function): Execute button actions on database rows
Key Features:
- Type Safety: Full TypeScript support with generics for data types
- Advanced Querying: MongoDB-style query syntax with
$and,$or,$eq,$ne, etc. - Sorting & Pagination: Flexible sorting and pagination options
- Bulk Operations: Efficient bulk updates and deletions
- Authentication: Support for both user (
auth-token) and server (api-token) authentication modes - Error Handling: Comprehensive error handling with meaningful error messages
Basic CRUD Example:
import { useDatabase } from '@emd-cloud/react-components';
// Define your data type for type safety
interface User {
_id?: string;
name: string;
email: string;
status: 'active' | 'inactive';
createdAt?: string;
}
const UserManagement = () => {
const { getRows, createRow, updateRow, deleteRow } = useDatabase();
// Get all active users
const loadActiveUsers = async () => {
try {
const response = await getRows<User>('users', {
query: {
"$and": [
{ "data.status": { "$eq": "active" } }
]
},
limit: 50,
sort: [{ column: "createdAt", sort: "desc" }]
});
console.log('Active users:', response.data);
console.log('Total count:', response.count);
} catch (error) {
console.error('Failed to load users:', error);
}
};
// Create a new user
const createUser = async (userData: Omit<User, '_id' | 'createdAt'>) => {
try {
const response = await createRow<User>('users', userData);
console.log('Created user:', response.data);
return response.data;
} catch (error) {
console.error('Failed to create user:', error);
throw error;
}
};
// Update user status
const updateUserStatus = async (userId: string, status: User['status']) => {
try {
const response = await updateRow<User>('users', userId, { status });
console.log('Updated user:', response.data);
return response.data;
} catch (error) {
console.error('Failed to update user:', error);
throw error;
}
};
// Delete a user
const removeUser = async (userId: string) => {
try {
await deleteRow('users', userId);
console.log('User deleted successfully');
} catch (error) {
console.error('Failed to delete user:', error);
throw error;
}
};
return (
<div>
<button onClick={loadActiveUsers}>Load Active Users</button>
<button onClick={() => createUser({
name: 'John Doe',
email: '[email protected]',
status: 'active'
})}>
Create User
</button>
</div>
);
};Advanced Querying Example:
import { useDatabase, DatabaseQuery } from '@emd-cloud/react-components';
const AdvancedUserSearch = () => {
const { getRows, countRows } = useDatabase();
// Complex query with multiple conditions
const searchUsers = async () => {
const query: DatabaseQuery = {
"$and": [
{
"$or": [
{ "data.name": { "$regex": "John", "$options": "i" } },
{ "data.email": { "$regex": "@gmail.com" } }
]
},
{ "data.status": { "$eq": "active" } },
{ "data.createdAt": { "$gte": "2024-01-01" } }
]
};
try {
// Get matching users with pagination
const usersResponse = await getRows('users', {
query,
limit: 20,
offset: 0,
sort: [
{ column: "name", sort: "asc" },
{ column: "createdAt", sort: "desc" }
]
});
// Count total matching users
const countResponse = await countRows('users', { query });
console.log('Found users:', usersResponse.data);
console.log('Total matching users:', countResponse.count);
} catch (error) {
console.error('Search failed:', error);
}
};
// Search by date range
const getUsersByDateRange = async (startDate: string, endDate: string) => {
try {
const response = await getRows('users', {
query: {
"data.createdAt": {
"$gte": startDate,
"$lte": endDate
}
},
sort: [{ column: "createdAt", sort: "desc" }]
});
return response.data;
} catch (error) {
console.error('Date range search failed:', error);
return [];
}
};
return (
<div>
<button onClick={searchUsers}>Advanced Search</button>
<button onClick={() => getUsersByDateRange('2024-01-01', '2024-12-31')}>
Users This Year
</button>
</div>
);
};Bulk Operations Example:
import { useDatabase } from '@emd-cloud/react-components';
const BulkUserOperations = () => {
const { bulkUpdate, deleteRows, getRows } = useDatabase();
// Bulk update user statuses
const activateAllPendingUsers = async () => {
try {
const response = await bulkUpdate('users', {
query: {
"data.status": { "$eq": "pending" }
},
update: {
"$set": { "data.status": "active" }
}
});
console.log('Bulk update result:', response);
console.log(`Updated ${response.modifiedCount} users`);
} catch (error) {
console.error('Bulk update failed:', error);
}
};
// Delete inactive users older than 6 months
const cleanupInactiveUsers = async () => {
const sixMonthsAgo = new Date();
sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6);
try {
const response = await deleteRows('users', {
query: {
"$and": [
{ "data.status": { "$eq": "inactive" } },
{ "data.lastLoginAt": { "$lt": sixMonthsAgo.toISOString() } }
]
}
});
console.log(`Deleted ${response.deletedCount} inactive users`);
} catch (error) {
console.error('Cleanup failed:', error);
}
};
// Get users with specific IDs
const getUsersByIds = async (userIds: string[]) => {
try {
const response = await getRows('users', {
query: {
"_id": { "$in": userIds }
}
});
return response.data;
} catch (error) {
console.error('Failed to get users by IDs:', error);
return [];
}
};
return (
<div>
<button onClick={activateAllPendingUsers}>Activate Pending Users</button>
<button onClick={cleanupInactiveUsers}>Cleanup Inactive Users</button>
</div>
);
};Authentication Modes Example:
import { useDatabase } from '@emd-cloud/react-components';
const ServerOperations = () => {
const { getRows, createRow } = useDatabase();
// Use server authentication for admin operations
const getAdminData = async () => {
try {
const response = await getRows('admin_logs', {
query: { "data.level": { "$eq": "error" } },
limit: 100
}, {
authType: 'api-token' // Use server authentication
});
console.log('Admin logs:', response.data);
} catch (error) {
console.error('Admin operation failed:', error);
}
};
// User-level operation (default auth-token)
const getUserProfile = async (userId: string) => {
try {
const response = await getRows('user_profiles', {
query: { "_id": { "$eq": userId } }
}); // Uses default auth-token authentication
return response.data[0];
} catch (error) {
console.error('Profile fetch failed:', error);
return null;
}
};
return (
<div>
<button onClick={getAdminData}>Get Admin Data</button>
<button onClick={() => getUserProfile('user-123')}>Get User Profile</button>
</div>
);
};Button Trigger Example:
import { useDatabase } from '@emd-cloud/react-components';
const WorkflowActions = () => {
const { triggerButton } = useDatabase();
// Trigger a workflow button on a specific row
const approveApplication = async (applicationId: string) => {
try {
const response = await triggerButton(
'applications', // Collection name
applicationId, // Row ID
'approve_button' // Button identifier
);
console.log('Application approved:', response);
} catch (error) {
console.error('Approval failed:', error);
}
};
// Trigger with custom authentication
const triggerAdminAction = async (recordId: string) => {
try {
const response = await triggerButton(
'admin_records',
recordId,
'admin_action_button',
{ authType: 'api-token' }
);
console.log('Admin action completed:', response);
} catch (error) {
console.error('Admin action failed:', error);
}
};
return (
<div>
<button onClick={() => approveApplication('app-123')}>
Approve Application
</button>
<button onClick={() => triggerAdminAction('record-456')}>
Trigger Admin Action
</button>
</div>
);
};Webhook Hooks:
Hook: useWebhook
Description:
The useWebhook hook provides easy integration with EMD Cloud webhook endpoints using the EMD Cloud SDK. It offers convenient methods for calling webhooks with different HTTP methods and payload formats, supporting both user and server authentication modes. This hook simplifies webhook integration for notifications, external process triggers, data fetching, and third-party service integrations.
Available Methods:
callWebhook(function): Make webhook calls with full control over HTTP method, headers, and body
Key Features:
- Custom Requests: Full control over HTTP method, headers, and request body
- Simple JSON Sending: Easy POST requests with JSON payloads
- GET Requests: Fetch data from webhook endpoints
- Authentication: Support for both
auth-token(user) andapi-token(server) authentication modes - Error Handling: Comprehensive error handling and response validation
- Type Safety: Full TypeScript support for webhook responses
Basic Usage Example:
import { useWebhook } from '@emd-cloud/react-components';
const NotificationComponent = () => {
const { callWebhook } = useWebhook();
// Send a simple notification
const sendUserLoginNotification = async (userId: string) => {
try {
const result = await callWebhook('user-login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
userId,
timestamp: new Date().toISOString(),
source: 'web-app',
userAgent: navigator.userAgent
})
});
console.log('Notification sent:', result);
} catch (error) {
console.error('Failed to send notification:', error);
}
};
// Get webhook status or configuration
const checkWebhookStatus = async () => {
try {
const status = await callWebhook('health-check', { method: 'GET' });
console.log('Webhook status:', status);
return status;
} catch (error) {
console.error('Failed to check webhook status:', error);
return null;
}
};
// Custom webhook call with specific requirements
const triggerProcessing = async (data: any) => {
try {
const result = await callWebhook('data-processor', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-Processing-Priority': 'high',
'X-Request-ID': crypto.randomUUID()
},
body: JSON.stringify({
action: 'process',
data,
timestamp: Date.now()
})
});
console.log('Processing triggered:', result);
return result;
} catch (error) {
console.error('Failed to trigger processing:', error);
throw error;
}
};
return (
<div>
<button onClick={() => sendUserLoginNotification('user-123')}>
Send Login Notification
</button>
<button onClick={checkWebhookStatus}>
Check Webhook Status
</button>
<button onClick={() => triggerProcessing({ type: 'user-data', id: 'user-123' })}>
Trigger Data Processing
</button>
</div>
);
};Event Notifications Example:
import { useWebhook } from '@emd-cloud/react-components';
const EventSystem = () => {
const { callWebhook } = useWebhook();
// User activity tracking
const trackUserActivity = async (activity: {
userId: string;
action: string;
page: string;
data?: any;
}) => {
try {
await callWebhook('user-activity', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
...activity,
timestamp: new Date().toISOString(),
sessionId: sessionStorage.getItem('sessionId'),
userAgent: navigator.userAgent
})
});
} catch (error) {
console.error('Failed to track activity:', error);
}
};
// Order processing notifications
const notifyOrderEvent = async (
event: 'created' | 'updated' | 'completed' | 'cancelled',
orderData: any
) => {
try {
await callWebhook(`order-${event}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
event,
order: orderData,
timestamp: new Date().toISOString(),
source: 'ecommerce-app'
})
});
console.log(`Order ${event} notification sent`);
} catch (error) {
console.error(`Failed to send order ${event} notification:`, error);
}
};
// Error reporting
const reportError = async (error: Error, context: any) => {
try {
await callWebhook('error-report', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
error: {
message: error.message,
stack: error.stack,
name: error.name
},
context,
timestamp: new Date().toISOString(),
url: window.location.href,
userAgent: navigator.userAgent
})
});
} catch (webhookError) {
console.error('Failed to report error via webhook:', webhookError);
}
};
return (
<div>
<button onClick={() => trackUserActivity({
userId: 'user-123',
action: 'page_view',
page: '/dashboard'
})}>
Track Page View
</button>
<button onClick={() => notifyOrderEvent('created', {
id: 'order-456',
total: 99.99,
items: ['item1', 'item2']
})}>
Notify Order Created
</button>
</div>
);
};Third-Party Integration Example:
import { useWebhook } from '@emd-cloud/react-components';
const ThirdPartyIntegrations = () => {
const { callWebhook } = useWebhook();
// Slack notification integration
const sendSlackNotification = async (message: string, channel: string) => {
try {
const result = await callWebhook('slack-notification', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
channel,
text: message,
username: 'EMD Cloud Bot',
timestamp: new Date().toISOString()
})
});
console.log('Slack notification sent:', result);
} catch (error) {
console.error('Failed to send Slack notification:', error);
}
};
// Email service integration
const sendEmail = async (to: string, subject: string, body: string) => {
try {
const result = await callWebhook('email-service', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Email-Priority': 'normal'
},
body: JSON.stringify({
to,
subject,
body,
from: '[email protected]',
timestamp: new Date().toISOString()
})
});
console.log('Email sent:', result);
return result;
} catch (error) {
console.error('Failed to send email:', error);
throw error;
}
};
// External API data sync
const syncWithCRM = async (customerData: any) => {
try {
const result = await callWebhook('crm-sync', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'X-Sync-Source': 'web-app'
},
body: JSON.stringify({
action: 'update_customer',
data: customerData,
syncTimestamp: new Date().toISOString()
})
});
console.log('CRM sync completed:', result);
return result;
} catch (error) {
console.error('CRM sync failed:', error);
throw error;
}
};
// Get integration status
const checkIntegrationHealth = async () => {
try {
const [slackStatus, emailStatus, crmStatus] = await Promise.all([
call('slack-health', { method: 'GET' }),
call('email-health', { method: 'GET' }),
call('crm-health', { method: 'GET' })
]);
return {
slack: slackStatus,
email: emailStatus,
crm: crmStatus
};
} catch (error) {
console.error('Failed to check integration health:', error);
return null;
}
};
return (
<div>
<button onClick={() => sendSlackNotification('Hello from EMD Cloud!', '#general')}>
Send Slack Message
</button>
<button onClick={() => sendEmail(
'[email protected]',
'Welcome to Our Service',
'Thank you for signing up!'
)}>
Send Welcome Email
</button>
<button onClick={() => syncWithCRM({
id: 'customer-123',
name: 'John Doe',
email: '[email protected]'
})}>
Sync with CRM
</button>
<button onClick={checkIntegrationHealth}>
Check Integration Health
</button>
</div>
);
};Server Authentication Example:
import { useWebhook } from '@emd-cloud/react-components';
const AdminWebhookOperations = () => {
const { callWebhook } = useWebhook();
// Server-level operations requiring API token
const triggerSystemMaintenance = async () => {
try {
const result = await callWebhook('system-maintenance', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Maintenance-Type': 'scheduled'
},
body: JSON.stringify({
action: 'start_maintenance',
duration: '30m',
timestamp: new Date().toISOString()
})
}, {
authType: 'api-token' // Use server authentication
});
console.log('Maintenance triggered:', result);
} catch (error) {
console.error('Failed to trigger maintenance:', error);
}
};
// Send admin notifications
const sendAdminAlert = async (alertType: string, message: string) => {
try {
await callWebhook('admin-alerts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
type: alertType,
message,
severity: 'high',
timestamp: new Date().toISOString(),
source: 'admin-panel'
})
}, {
authType: 'api-token'
});
console.log('Admin alert sent');
} catch (error) {
console.error('Failed to send admin alert:', error);
}
};
// User-level webhook (default auth-token)
const sendUserFeedback = async (feedback: string) => {
try {
await callWebhook('user-feedback', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
feedback,
timestamp: new Date().toISOString(),
page: window.location.pathname
})
}); // Uses default auth-token
console.log('Feedback submitted');
} catch (error) {
console.error('Failed to submit feedback:', error);
}
};
return (
<div>
<button onClick={triggerSystemMaintenance}>
Trigger System Maintenance
</button>
<button onClick={() => sendAdminAlert('system_overload', 'CPU usage is above 90%')}>
Send Admin Alert
</button>
<button onClick={() => sendUserFeedback('Great app!')}>
Send User Feedback
</button>
</div>
);
};Error Handling and Response Validation:
import { useWebhook } from '@emd-cloud/react-components';
const RobustWebhookComponent = () => {
const { callWebhook } = useWebhook();
// Webhook with retry logic
const sendWithRetry = async (webhookId: string, data: any, maxRetries = 3) => {
let lastError: Error;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const result = await callWebhook(webhookId, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
...data,
attempt,
timestamp: new Date().toISOString()
})
});
console.log(`Webhook succeeded on attempt ${attempt}:`, result);
return result;
} catch (error) {
lastError = error as Error;
console.warn(`Webhook attempt ${attempt} failed:`, error);
if (attempt < maxRetries) {
// Wait before retry (exponential backoff)
await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
}
}
}
throw new Error(`Webhook failed after ${maxRetries} attempts: ${lastError.message}`);
};
// Validate webhook response
const callWebhookWithValidation = async (webhookId: string, options: RequestInit) => {
try {
const result = await callWebhook(webhookId, options);
// Custom validation logic
if (result && typeof result === 'object' && 'status' in result) {
if (result.status === 'error') {
throw new Error(`Webhook returned error: ${result.message || 'Unknown error'}`);
}
}
return result;
} catch (error) {
console.error('Webhook validation failed:', error);
// Log error details for debugging
console.error('Webhook details:', {
webhookId,
method: options.method || 'GET',
headers: options.headers,
timestamp: new Date().toISOString()
});
throw error;
}
};
// Bulk webhook operations with error collection
const sendBulkNotifications = async (notifications: Array<{id: string, data: any}>) => {
const results = [];
const errors = [];
for (const notification of notifications) {
try {
const result = await callWebhook(notification.id, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(notification.data)
});
results.push({ id: notification.id, success: true, result });
} catch (error) {
errors.push({ id: notification.id, error: error.message });
}
}
console.log(`Bulk notifications: ${results.length} succeeded, ${errors.length} failed`);
if (errors.length > 0) {
console.warn('Failed notifications:', errors);
}
return { results, errors };
};
return (
<div>
<button onClick={() => sendWithRetry('unreliable-webhook', { test: 'data' })}>
Send with Retry Logic
</button>
<button onClick={() => callWebhookWithValidation('validation-webhook', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ validate: true })
})}>
Call with Validation
</button>
<button onClick={() => sendBulkNotifications([
{ id: 'notification-1', data: { message: 'Hello 1' } },
{ id: 'notification-2', data: { message: 'Hello 2' } },
{ id: 'notification-3', data: { message: 'Hello 3' } }
])}>
Send Bulk Notifications
</button>
</div>
);
};Chat Hooks:
Hook: useChat
Description:
The useChat hook provides comprehensive REST API operations for managing chat channels and messages in EMD Cloud using the EMD Cloud SDK. It offers complete chat functionality including channel creation, message sending, unread tracking, and support for multiple channel types (public, staff-to-user, peer-to-peer, and staff channels). This hook automatically manages authentication and provides error handling for all chat operations.
Available Methods:
listChannels(function): List chat channels with filtering and paginationcreateChannelByType(function): Create or get existing channel by typeupsertChannel(function): Create or update a chat channelgetChannel(function): Get channel detailsdeleteChannel(function): Delete a chat channelsendMessage(function): Send a message with optional attachmentslistMessages(function): List messages in a channel with paginationdeleteMessage(function): Delete a messagegetUnreadCount(function): Get unread message counts for a channel
Key Features:
- Channel Management: Create, list, update, and delete chat channels
- Multiple Channel Types: Support for public, staff-to-user, peer-to-peer, and staff channels
- Message Operations: Send, list, and delete messages with attachment support
- Unread Tracking: Track and clear unread message counts
- Search & Pagination: Search channels/messages with flexible pagination
- Attachment Support: Send images, files, and other attachments with messages
- Type Safety: Full TypeScript support with SDK types
- Error Handling: Comprehensive error handling with meaningful messages
Basic Channel Management Example:
import { useChat, ChatChannelType } from '@emd-cloud/react-components';
import { useState, useEffect } from 'react';
const ChannelManager = () => {
const [channels, setChannels] = useState([]);
const { listChannels, createChannelByType, deleteChannel } = useChat();
// Load public channels
const loadPublicChannels = async () => {
try {
const response = await listChannels({
type: ChatChannelType.Public,
limit: 20,
sort: 'DESC',
orderBy: 'lastMessageAt'
});
setChannels(response.data);
console.log(`Found ${response.count} channels`);
} catch (error) {
console.error('Failed to load channels:', error);
}
};
// Create a support channel
const createSupportChannel = async (userId: string) => {
try {
const channel = await createChannelByType(ChatChannelType.StaffToUser, {
userId
});
console.log('Support channel created:', channel.id);
return channel;
} catch (error) {
console.error('Failed to create support channel:', error);
}
};
// Create a direct message channel
const createDirectMessage = async (userIds: string[]) => {
try {
const channel = await createChannelByType(ChatChannelType.PeerToPeer, {
accesses: userIds
});
console.log('DM channel created:', channel.id);
return channel;
} catch (error) {
console.error('Failed to create DM channel:', error);
}
};
// Delete a channel
const removeChannel = async (channelId: string) => {
try {
await deleteChannel(channelId);
console.log('Channel deleted');
loadPublicChannels(); // Refresh list
} catch (error) {
console.error('Failed to delete channel:', error);
}
};
useEffect(() => {
loadPublicChannels();
}, []);
return (
<div>
<h3>Chat Channels</h3>
<button onClick={loadPublicChannels}>Refresh Channels</button>
<button onClick={() => createSupportChannel('user-123')}>
Create Support Channel
</button>
<button onClick={() => createDirectMessage(['user-1', 'user-2'])}>
Create DM
</button>
<ul>
{channels.map((channel) => (
<li key={channel._id}>
<span>{channel.id}</span>
{channel.unreadCountRecipient > 0 && (
<span className="badge">{channel.unreadCountRecipient}</span>
)}
<button onClick={() => removeChannel(channel._id)}>Delete</button>
</li>
))}
</ul>
</div>
);
};Message Operations Example:
import { useChat } from '@emd-cloud/react-components';
import { useState, useEffect } from 'react';
const ChatConversation = ({ channelId }: { channelId: string }) => {
const [messages, setMessages] = useState([]);
const [messageText, setMessageText] = useState('');
const { sendMessage, listMessages, deleteMessage, getUnreadCount } = useChat();
// Load messages
const loadMessages = async () => {
try {
const response = await listMessages(channelId, {
limit: 50,
page: 0,
orderBy: 'createdAt',
sort: 'DESC'
});
setMessages(response.data.reverse()); // Show oldest first
} catch (error) {
console.error('Failed to load messages:', error);
}
};
// Send a text message
const handleSendMessage = async () => {
if (!messageText.trim()) return;
try {
const message = await sendMessage(channelId, {
message: messageText
});
setMessages(prev => [...prev, message]);
setMessageText('');
} catch (error) {
console.error('Failed to send message:', error);
}
};
// Send message with attachments
const sendMessageWithFiles = async (fileIds: string[]) => {
try {
const message = await sendMessage(channelId, {
message: 'Sent some files',
attaches: fileIds.map(id => ({
type: 'file',
attach: id,
name: `file-${id}`
}))
});
setMessages(prev => [...prev, message]);
} catch (error) {
console.error('Failed to send message with files:', error);
}
};
// Delete a message
const handleDeleteMessage = async (messageId: string) => {
try {
await deleteMessage(channelId, messageId);
setMessages(prev => prev.filter(m => m._id !== messageId));
} catch (error) {
console.error('Failed to delete message:', error);
}
};
// Check unread count and mark as read
const markAsRead = async () => {
try {
const counts = await getUnreadCount(channelId, {
cleanupUnreaded: true // Mark as read
});
console.log('Unread cleared:', counts);
} catch (error) {
console.error('Failed to mark as read:', error);
}
};
useEffect(() => {
loadMessages();
markAsRead();
}, [channelId]);
return (
<div>
<h3>Conversation</h3>
<div className="messages">
{messages.map((message) => (
<div key={message._id} className="message">
<p>{message.message}</p>
{message.attaches?.map((attach) => (
<div key={attach._id}>
<a href={`/files/${attach.attach}`}>{attach.name}</a>
</div>
))}
<button onClick={() => handleDeleteMessage(message._id)}>
Delete
</button>
</div>
))}
</div>
<div className="input">
<input
value={messageText}
onChange={(e) => setMessageText(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && handleSendMessage()}
placeholder="Type a message..."
/>
<button onClick={handleSendMessage}>Send</button>
</div>
</div>
);
};Search and Filtering Example:
import { useChat, ChatChannelType } from '@emd-cloud/react-components';
import { useState } from 'react';
const ChatSearch = () => {
const [searchQuery, setSearchQuery] = useState('');
const [results, setResults] = useState([]);
const { listChannels, listMessages } = useChat();
// Search channels
const searchChannels = async () => {
try {
const response = await listChannels({
type: ChatChannelType.Public,
search: searchQuery,
limit: 20
});
setResults(response.data);
console.log(`Found ${response.count} matching channels`);
} catch (error) {
console.error('Search failed:', error);
}
};
// Search messages in a channel
const searchMessages = async (channelId: string) => {
try {
const response = await listMessages(channelId, {
search: searchQuery,
limit: 100
});
return response.data;
} catch (error) {
console.error('Message search failed:', error);
return [];
}
};
// Get unread chats only
const getUnreadChats = async () => {
try {
const response = await listChannels({
type: ChatChannelType.StaffToUser,
unreadedChats: true,
limit: 50
});
setResults(response.data);
console.log(`${response.count} unread chats`);
} catch (error) {
console.error('Failed to get unread chats:', error);
}
};
return (
<div>
<input
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
placeholder="Search channels..."
/>
<button onClick={searchChannels}>Search Channels</button>
<button onClick={getUnreadChats}>Show Unread</button>
<ul>
{results.map((channel) => (
<li key={channel._id}>
{channel.id}
{channel.unreadCountRecipient > 0 && (
<span> ({channel.unreadCountRecipient} unread)</span>
)}
</li>
))}
</ul>
</div>
);
};Hook: useChatWebSocket
Description:
The useChatWebSocket hook provides real-time chat messaging functionality via WebSocket connection using the EMD Cloud SDK. It implements the Pusher WebSocket protocol for live message updates, connection management, channel subscriptions, and event handling. The hook offers automatic reconnection, connection state tracking, and React-friendly lifecycle management with automatic cleanup.
Available Methods & Properties:
connect()(function): Connect to the WebSocket serverdisconnect()(function): Disconnect from the WebSocket serversubscribeToChannel(channelId, chatId?)(function): Subscribe to a chat channelunsubscribeFromChannel(channelId)(function): Unsubscribe from a channelsubscribeToSupport()(function): Subscribe to support channel (staff only)setCallbacks(callbacks)(function): Set or update event callbacksgetConnectionState()(function): Get current connection stategetSubscribedChannels()(function): Get list of subscribed channelsconnectionState(property): Reactive connection stateisConnected(property): Boolean indicating if connected
Key Features:
- Real-time Messaging: Receive messages instantly via WebSocket
- Auto-reconnect: Automatic reconnection with exponential backoff
- Connection Management: Connect, disconnect, and track connection state
- Channel Subscriptions: Subscribe/unsubscribe to multiple channels
- Event Callbacks: Handle message received, deleted, and connection state changes
- Auto-cleanup: Automatic disconnect on component unmount
- Type Safety: Full TypeScript support for all events
- Support Integration: Subscribe to support channel for staff notifications
Basic WebSocket Connection Example:
import { useChatWebSocket, ConnectionState } from '@emd-cloud/react-components';
import { useEffect, useState } from 'react';
const ChatComponent = () => {
const [messages, setMessages] = useState([]);
const {
connect,
disconnect,
subscribeToChannel,
connectionState,
isConnected
} = useChatWebSocket({
autoConnect: true, // Connect automatically on mount
autoReconnect: true,
maxReconnectAttempts: 10,
callbacks: {
onMessageReceived: (message) => {
console.log('New message:', message);
setMessages(prev => [...prev, message]);
},
onMessageDeleted: (data) => {
console.log('Message deleted:', data._id);
setMessages(prev => prev.filter(m => m._id !== data._id));
},
onConnectionStateChange: (state) => {
console.log('Connection state:', state);
},
onError: (error) => {
console.error('WebSocket error:', error);
}
}
});
// Subscribe to a channel when connected
useEffect(() => {
if (isConnected) {
subscribeToChannel('public-general')
.then(() => console.log('Subscribed to channel'))
.catch((error) => console.error('Subscription failed:', error));
}
}, [isConnected]);
return (
<div>
<div className="status">
<p>Status: {connectionState}</p>
{!isConnected && <button onClick={connect}>Connect</button>}
{isConnected && <button onClick={disconnect}>Disconnect</button>}
</div>
<div className="messages">
{messages.map((msg) => (
<div key={msg._id}>
<strong>{msg.user}:</strong> {msg.message}
</div>
))}
</div>
</div>
);
};Advanced Channel Management Example:
import { useChatWebSocket, useChat } from '@emd-cloud/react-components';
import { useEffect, useState } from 'react';
const MultiChannelChat = () => {
const [activeChannels, setActiveChannels] = useState<string[]>([]);
const [messagesByChannel, setMessagesByChannel] = useState<Record<string, any[]>>({});
const { listChannels, sendMessage } = useChat();
const {
connect,
subscribeToChannel,
unsubscribeFromChannel,
setCallbacks,
connectionState,
isConnected,
getSubscribedChannels
} = useChatWebSocket({
autoConnect: false, // Manual connection control
autoReconnect: true,
reconnectDelay: 1000,
maxReconnectDelay: 30000
});
// Set up callbacks
useEffect(() => {
setCallbacks({
onMessageReceived: (message) => {
const channelId = typeof message.channel === 'string'
? message.channel
: message.channel.id;
setMessagesByChannel(prev => ({
...prev,
[channelId]: [...(prev[channelId] || []), message]
}));
},
onMessageDeleted: (data) => {
setMessagesByChannel(prev => {
const updated = { ...prev };
if (updated[data.channel]) {
updated[data.channel] = updated[data.channel].filter(
m => m._id !== data._id
);
}
return updated;
});
}
});
}, []);
// Load and subscribe to channels
const loadAndSubscribeToChannels = async () => {
try {
if (!isConnected) {
await connect();
}
const response = await listChannels({
type: 'public' as any,
limit: 10
});
const channelIds = response.data.map(ch => ch.id);
setActiveChannels(channelIds);
// Subscribe to all channels
for (const channelId of channelIds) {
await subscribeToChannel(channelId);
}
console.log(`Subscribed to ${channelIds.length} channels`);
} catch (error) {
console.error('Failed to load channels:', error);
}
};
// Join a specific channel
const joinChannel = async (channelId: string) => {
try {
if (!isConnected) {
await connect();
}
await subscribeToChannel(channelId);
setActiveChannels(prev => [...prev, channelId]);
console.log(`Joined channel: ${channelId}`);
} catch (error) {
console.error('Failed to join channel:', error);
}
};
// Leave a channel
const leaveChannel = (channelId: string) => {
unsubscribeFromChannel(channelId);
setActiveChannels(prev => prev.filter(id => id !== channelId));
console.log(`Left channel: ${channelId}`);
};
// Send message to active channel
const sendToChannel = async (channelId: string, text: string) => {
try {
await sendMessage(channelId, { message: text });
} catch (error) {
console.error('Failed to send message:', error);
}
};
return (
<div>
<div className="header">
<p>Connection: {connectionState}</p>
<p>Channels: {activeChannels.length}</p>
<button onClick={loadAndSubscribeToChannels}>
Load Channels
</button>
</div>
<div className="channels">
{activeChannels.map((channelId) => (
<div key={channelId} className="channel">
<h4>{channelId}</h4>
<button onClick={() => leaveChannel(channelId)}>Leave</button>
<div className="messages">
{(messagesByChannel[channelId] || []).map((msg) => (
<div key={msg._id}>{msg.message}</div>
))}
</div>
<input
onKeyPress={(e) => {
if (e.key === 'Enter') {
sendToChannel(channelId, e.currentTarget.value);
e.currentTarget.value = '';
}
}}
placeholder="Type a message..."
/>
</div>
))}
</div>
</div>
);
};Support Channel Integration Example:
import { useChatWebSocket } from '@emd-cloud/react-components';
import { useState, useEffect } from 'react';
const StaffSupportDashboard = () => {
const [supportCount, setSupportCount] = useState(0);
const [supportChannels, setSupportChannels] = useState([]);
const {
connect,
subscribeToSupport,
subscribeToChannel,
setCallbacks,
isConnected
} = useChatWebSocket({
autoConnect: true
});
useEffect(() => {
// Set up support-specific callbacks
setCallbacks({
onSupportCountUpdated: (data) => {
console.log('Unread support messages:', data.count);
setSupportCount(data.count);
},
onSupportChannelUpdated: (channel) => {
console.log('Support channel updated:', channel);
setSupportChannels(prev => {
const index = prev.findIndex(ch => ch._id === channel._id);
if (index >= 0) {
const updated = [...prev];
updated[index] = channel;
return updated;
}
return [...prev, channel];
});
},
onMessageReceived: (message) => {
console.log('New support message:', message);
// Handle new message in support channel
}
});
}, []);
// Subscribe to support channel when connected
useEffect(() => {
if (isConnected) {
subscribeToSupport()
.then(() => console.log('Subscribed to support channel'))
.catch((error) => console.error('Support subscription failed:', error));
}
}, [isConnected]);
// Subscribe to individual support channels
const subscribeToSupportChannel = async (channelId: string) => {
try {
await subscribeToChannel(channelId, channelId);
console.log(`Subscribed to support channel: ${channelId}`);
} catch (error) {
console.error('Failed to subscribe to support channel:', error);
}
};
return (
<div>
<h3>Staff Support Dashboard</h3>
<div className="stats">
<p>Unread Support Messages: {supportCount}</p>
<p>Active Support Channels: {supportChannels.length}</p>
</div>
<div className="support-channels">
{supportChannels.map((channel) => (
<div key={channel._id} className="support-channel">
<h4>{channel.id}</h4>
<p>Unread: {channel.unreadCountCreator || 0}</p>
<p>Resolved: {channel.resolved ? 'Yes' : 'No'}</p>
<button onClick={() => subscribeToSupportChannel(channel.id)}>
Join Channel
</button>
</div>
))}
</div>
</div>
);
};Connection State Management Example:
import { useChatWebSocket, ConnectionState } from '@emd-cloud/react-components';
import { useEffect, useState } from 'react';
const ConnectionMonitor = () => {
const [connectionHistory, setConnectionHistory] = useState<string[]>([]);
const [reconnectAttempts, setReconnectAttempts] = useState(0);
const {
connect,
disconnect,
connectionState,
isConnected,
getConnectionState
} = useChatWebSocket({
autoConnect: false,
autoReconnect: true,
maxReconnectAttempts: 5,
reconnectDelay: 2000,
callbacks: {
onConnectionStateChange: (state) => {
const timestamp = new Date().toLocaleTimeString();
setConnectionHistory(prev => [
...prev,
`${timestamp}: ${state}`
]);
if (state === ConnectionState.Connecting) {
setReconnectAttempts(prev => prev + 1);
} else if (state === ConnectionState.Connected) {
setReconnectAttempts(0);
}
},
onError: (error) => {
console.error('Connection error:', error.message);
}
}
});
// Manual connection control
const handleConnect = async () => {
try {
await connect();
console.log('Connected successfully');
} catch (error) {
console.error('Connection failed:', error);
}
};
const handleDisconnect = () => {
disconnect();
console.log('Disconnected');
};
// Monitor connection state
useEffect(() => {
const interval = setInterval(() => {
const currentState = getConnectionState();
console.log('Current state:', currentState);
}, 5000);
return () => clearInterval(interval);
}, []);
return (
<div>
<h3>WebSocket Connection Monitor</h3>
<div className="status">
<p>State: <strong>{connectionState}</strong></p>
<p>Connected: {isConnected ? 'Yes' : 'No'}</p>
<p>Reconnect Attempts: {reconnectAttempts}</p>
</div>
<div className="controls">
<button onClick={handleConnect} disabled={isConnected}>
Connect
</button>
<button onClick={handleDisconnect} disabled={!isConnected}>
Disconnect
</button>
</div>
<div className="history">
<h4>Connection History</h4>
<ul>
{connectionHistory.map((entry, index) => (
<li key={index}>{entry}</li>
))}
</ul>
</div>
</div>
);
};Uploader Hooks:
Hook: useUploader
Description:
This hook provides file upload functionality to EMD Cloud storage using the SDK's TUS (resumable upload) protocol implementation. It manages multiple concurrent file uploads with progress tracking, automatic retries, and flexible permission settings. The hook integrates seamlessly with the ApplicationProvider and handles all aspects of the upload lifecycle including progress updates, error handling, and upload cancellation.
Key Features:
- Resumable Uploads: Uses TUS protocol for reliable uploads that can survive connection interruptions
- Multiple File Support: Upload multiple files simultaneously with independent progress tracking
- Progress Tracking: Real-time progress updates with bytes uploaded, total bytes, and percentage
- Flexible Permissions: Support for public, authenticated users, staff only, or specific user access
- Chunked Upload: Large file support with configurable chunk size (default: 5MB)
- Automatic Retry: Configurable retry delays for failed upload chunks
- Upload Control: Ability to cancel/abort individual file uploads
- Request Interception: onBeforeRequest callback for request customization
- Type Safety: Full TypeScript support with SDK types
Parameters:
Note: The hook automatically uses apiUrl and app configuration from the ApplicationProvider context. Make sure your application is wrapped with ApplicationProvider before using this hook.
integration(string, optional): S3 integration identifier. Default:'default'chunkSize(number, optional): Size of each upload chunk in bytes. Default:5242880(5MB)headers(object, optional): Additional HTTP headers to include in upload requestsreadPermission(ReadPermission, optional): File access permission level. Options:ReadPermission.Public- File accessible to everyoneReadPermission.OnlyAuthUser- File accessible to all authenticated usersReadPermission.OnlyAppStaff- File accessible to uploader and app staff (default)ReadPermission.OnlyPermittedUsers- File accessible only to users inpermittedUsersarray
permittedUsers(string[], optional): Array of user IDs who can access the file (required whenreadPermissionisOnlyPermittedUsers)presignedUrlTTL(number, optional): Lifetime of generated presigned URLs in minutes. Default:60retryDelays(number[], optional): Array of delay intervals in milliseconds for retry attempts. Default:[0, 3000, 5000, 10000, 20000]onBeforeUpload(function, optional): Callback invoked before upload starts. Returnfalseto cancel upload. Default:() => trueonBeforeRequest(function, optional): Callback invoked before each HTTP request during upload (for request interception/modification)onUpdate(function, required): Callback invoked when file upload statuses change. Receives array of file objects with current status
Return Value: Returns an object with two properties:
uploadFiles(function): Function to initiate file uploads. Accepts an array of File objectsisProccess(boolean): Boolean flag indicating if any uploads are currently in progress
File Object Structure:
Each file in the onUpdate callback has the following structure:
{
id: string; // Unique upload ID
fileName: string; // Name of the file
status: 'started' | 'progress' | 'success' | 'failed';
progress?: string; // Upload progress percentage (e.g., "45.32")
bytesUploaded?: number; // Number of bytes uploaded
bytesTotal?: number; // Total file size in bytes
fileUrl?: string; // URL to access the file (available after success)
error?: Error; // Error object (if upload failed)
methods?: {
stop: () => void; // Function to cancel/abort the upload
};
}Basic Example:
