@actschurch/ccms-sdk
v0.0.4
Published
CCMS TypeScript SDK for Web APIs and WebSockets (Express, Web, React Native)
Maintainers
Readme
CCMS SDK
Official TypeScript/JavaScript SDK for the CCMS (Church/Community Management System) Platform. This SDK provides a comprehensive set of tools for building web and mobile applications that integrate with the CCMS backend.
Features
- Cross-Platform: Works seamlessly on Web (React, Vue, vanilla JS) and React Native
- TypeScript First: Full type definitions for all APIs and models
- Authentication: Complete auth flow with automatic token refresh
- Real-time Communication: SignalR-based presence tracking and log streaming with automatic reconnection
- Permission Management: Role-based access control with feature definitions
- React Integration: 50+ hooks and components for React applications
- Comprehensive Services: 15+ domain-specific service modules with 100+ API endpoints
- Utility Library: Extensive utilities for strings, dates, arrays, validation, and more
- Developer Experience: Auto-complete, type safety, and comprehensive documentation
What's New
Latest Updates
- 🚀 Enhanced Service Architecture: Comprehensive service modules covering 18 domains with 168+ services including Task Management (12 services), Communication (6 services), Procurement (18 services), Payments (14 services), Projects (17 services), HR (19 services), Meetings (14 services), and more. See Services for details.
- 📡 New Realtime Module: Completely redesigned real-time communication with SignalR-based hubs for presence tracking (with activity detection) and log streaming (application, API, query, and dashboard logs). See Real-time for migration guide.
- ⚛️ Expanded React Hooks: 18 service-specific hooks (
useTaskServices,useCommunicationServices,useMeetingsServices, etc.) and 8 dedicated realtime hooks for presence tracking and log streaming. - 🎨 Activity Detection: Automatic user status updates based on activity for both web (mouse, keyboard, visibility) and React Native (AppState) platforms.
- 📚 Comprehensive Documentation: Detailed module-level documentation for Services and Realtime.
Table of Contents
- What's New
- Installation
- Quick Start
- Core Concepts
- React Integration
- React Native Setup
- Services
- Utilities
- Models
- Testing
- API Reference
Installation
npm install @actschurch/ccms-sdk
# or
yarn add @actschurch/ccms-sdk
# or
pnpm add @actschurch/ccms-sdkPeer Dependencies
For React applications:
npm install react@^18.0.0Quick Start
Basic Setup (Vanilla JavaScript/TypeScript)
import { HttpClient, AuthManager, LocalStorageAdapter } from '@actschurch/ccms-sdk';
// Create HTTP client
const http = new HttpClient({
baseUrl: 'https://api.yourccms.com',
});
// Create auth manager with storage
const authManager = new AuthManager(http, {
storage: new LocalStorageAdapter(),
autoRefresh: true,
});
// Initialize auth (loads user from storage)
await authManager.initialize();
// Login
const user = await authManager.login({
email: '[email protected]',
password: 'password123',
});
// Make authenticated requests
const response = await http.get('/api/members');React Setup
import { CCMSProvider, useCCMS, useAuth } from '@actschurch/ccms-sdk';
// Wrap your app with CCMSProvider
function App() {
return (
<CCMSProvider
config={{
baseUrl: 'https://api.yourccms.com',
enableRealtime: true,
}}
>
<MyApp />
</CCMSProvider>
);
}
// Use hooks in your components
function Dashboard() {
const { http } = useCCMS();
const { user, isAuthenticated, login, logout } = useAuth();
if (!isAuthenticated) {
return <LoginForm onLogin={login} />;
}
return (
<div>
<h1>Welcome, {user?.firstName}!</h1>
<button onClick={logout}>Logout</button>
</div>
);
}Core Concepts
HTTP Client
The HttpClient is the foundation for all API communication. It handles request/response interceptors, authentication headers, and error handling.
import { HttpClient } from '@actschurch/ccms-sdk';
const http = new HttpClient({
baseUrl: 'https://api.yourccms.com',
timeout: 30000, // 30 seconds
headers: {
'X-Custom-Header': 'value',
},
});
// GET request
const members = await http.get<Member[]>('/api/members');
// POST request
const newMember = await http.post<Member>('/api/members', {
firstName: 'John',
lastName: 'Doe',
email: '[email protected]',
});
// PUT request
const updated = await http.put<Member>('/api/members/123', {
firstName: 'Jane',
});
// DELETE request
await http.delete('/api/members/123');
// Request with query parameters
const filtered = await http.get<Member[]>('/api/members', {
params: { status: 'active', page: 1, pageSize: 20 },
});Interceptors
Add request/response interceptors for logging, error handling, or modifying requests:
// Request interceptor
http.interceptors.request.use(
(config) => {
console.log('Request:', config.url);
return config;
},
(error) => Promise.reject(error)
);
// Response interceptor
http.interceptors.response.use(
(response) => {
console.log('Response:', response.status);
return response;
},
(error) => {
if (error.status === 401) {
// Handle unauthorized
}
return Promise.reject(error);
}
);Authentication
The AuthManager handles the complete authentication flow including login, logout, token refresh, and session persistence.
import { AuthManager, LocalStorageAdapter, MemoryStorageAdapter } from '@actschurch/ccms-sdk';
// Create auth manager
const authManager = new AuthManager(http, {
// Storage adapter (choose based on platform)
storage: new LocalStorageAdapter(), // Web
// storage: new AsyncStorageAdapter(AsyncStorage), // React Native
// storage: new MemoryStorageAdapter(), // SSR or testing
// Token refresh configuration
autoRefresh: true,
refreshThresholdSeconds: 60, // Refresh 60s before expiry
refreshCheckIntervalMs: 30000, // Check every 30s
// Callbacks
onLogin: (user) => console.log('User logged in:', user.email),
onLogout: () => console.log('User logged out'),
onRefresh: (user) => console.log('Token refreshed'),
onError: (error) => console.error('Auth error:', error),
});
// Initialize (loads persisted session)
const user = await authManager.initialize();
// Login
try {
const user = await authManager.login({
email: '[email protected]',
password: 'password123',
});
console.log('Logged in as:', user.firstName);
} catch (error) {
console.error('Login failed:', error.message);
}
// Get current state
const state = authManager.getState();
// { isAuthenticated: true, user: {...}, isLoading: false, error: null }
// Check permissions
if (authManager.hasRole('admin')) {
// User is admin
}
if (authManager.hasRight('members.edit')) {
// User can edit members
}
// Subscribe to state changes
const unsubscribe = authManager.subscribe((state) => {
console.log('Auth state changed:', state);
});
// Logout
await authManager.logout();
// Cleanup
unsubscribe();
authManager.destroy();Storage Adapters
Different storage adapters for different platforms:
import {
LocalStorageAdapter, // Web - localStorage
SessionStorageAdapter, // Web - sessionStorage
MemoryStorageAdapter, // In-memory (SSR/testing)
AsyncStorageAdapter, // React Native
SecureStorageAdapter, // React Native - secure storage
CookieStorageAdapter, // SSR/universal apps
GenericStorageAuthAdapter, // Custom storage
} from '@actschurch/ccms-sdk';
// React Native with AsyncStorage
import AsyncStorage from '@react-native-async-storage/async-storage';
const storage = new AsyncStorageAdapter(AsyncStorage);
// React Native with Expo SecureStore
import * as SecureStore from 'expo-secure-store';
const storage = new SecureStorageAdapter(SecureStore);
// Custom storage key
const storage = new LocalStorageAdapter('my_app_auth');Permissions
The PermissionManager handles feature-based access control using roles and permissions.
import { PermissionManager, defineFeature, requires } from '@actschurch/ccms-sdk';
// Create permission manager
const permissions = new PermissionManager({
defaultAllow: false,
debug: true,
});
// Define features with requirements
permissions.registerFeatures([
defineFeature('members.view', 'View Members', [
requires.anyRole(['admin', 'staff', 'member']),
]),
defineFeature('members.edit', 'Edit Members', [
requires.anyRole(['admin', 'staff']),
requires.right('members.write'),
]),
defineFeature('admin.dashboard', 'Admin Dashboard', [
requires.role('admin'),
]),
defineFeature('reports.financial', 'Financial Reports', [
requires.allRoles(['admin', 'finance']),
]),
defineFeature('custom.feature', 'Custom Feature', [
requires.custom(() => someCondition(), 'customCheck'),
]),
]);
// Set user context (usually done after login)
permissions.setContext({
roles: user.roles,
rights: user.rights,
isAuthenticated: true,
userId: user.id,
});
// Check permissions
if (permissions.can('members.edit')) {
// User can edit members
}
// Get detailed check result
const result = permissions.check('members.edit');
// { allowed: false, reason: '...', missing: ['members.write'] }
// Direct role/right checks
permissions.hasRole('admin');
permissions.hasAnyRole(['admin', 'staff']);
permissions.hasAllRoles(['admin', 'finance']);
permissions.hasRight('members.write');
permissions.hasAnyRight(['members.read', 'members.write']);
// Listen for denied access attempts
permissions.onDenied((event) => {
console.log('Access denied to feature:', event.featureId);
analytics.track('permission_denied', event);
});Real-time
The CCMS SDK provides robust real-time communication infrastructure using SignalR WebSockets with automatic reconnection, type-safe event handling, and React integration.
Key Features
- 🔄 Automatic Reconnection - Exponential backoff strategy with delays: [2s, 4s, 8s, 16s, 30s]
- 🔐 JWT Authentication - Seamless integration with CCMS auth system
- 📡 Multiple Hubs - Separate hubs for presence tracking (1 hub) and log streaming (4 hubs)
- ⚛️ React Integration - First-class React support with 8 dedicated hooks and context providers
- 📱 Cross-Platform - Works in web browsers and React Native applications
- 🎨 Activity Detection - Automatic user status updates based on platform-specific activity monitoring
- 🔌 Auto-Management - Automatic connection on login, disconnection on logout
For comprehensive documentation, see the Realtime Module Documentation.
Presence Tracking
Track user presence and status across the platform with automatic activity detection and real-time updates.
Features:
- Auto-Connect on Login - PresenceProvider automatically connects when user authenticates
- Activity Detection - Monitors user activity (web: mouse/keyboard/visibility; React Native: AppState)
- Auto-Away Status - Automatically sets status to "Away" after 5 minutes of inactivity
- Multi-Device Support - Handles multiple concurrent connections per user
- Status Broadcasting - Real-time updates broadcast to all connected clients
Available Statuses: Online, Away, Busy, Offline
import { PresenceProvider, usePresence, useUserPresence, useOnlineUsers, usePresenceStatus, PresenceStatus } from '@actschurch/ccms-sdk/realtime/presence';
// Setup in your app root with auto-connection management
function App() {
return (
<PresenceProvider
authManager={authManager}
baseUrl="https://api.example.com"
options={{
activityTimeout: 5 * 60 * 1000, // 5 minutes until "Away"
enableActivityDetection: true,
platform: 'web', // or 'react-native'
autoReconnect: true,
maxReconnectAttempts: 10,
}}
onConnectionChange={(connected) => console.log('Presence:', connected)}
>
<YourApp />
</PresenceProvider>
);
}
// Use in components - get specific user's presence
function UserStatus({ userId }: { userId: string }) {
const userPresence = useUserPresence(userId);
const { updateStatus } = usePresence();
return (
<div className="flex items-center gap-2">
<StatusIndicator status={userPresence?.status || 'Offline'} />
<span>{userPresence?.statusMessage || userPresence?.status}</span>
<button onClick={() => updateStatus(PresenceStatus.Busy, 'In a meeting')}>
Set Busy
</button>
</div>
);
}
// Show all online users
function OnlineUsersList() {
const onlineUsers = useOnlineUsers(); // Returns UserPresenceUpdate[]
const myStatus = usePresenceStatus();
return (
<div>
<p>My Status: {myStatus}</p>
<p>Online Users: {onlineUsers.length}</p>
<ul>
{onlineUsers.map(user => (
<li key={user.userId}>{user.userName} - {user.status}</li>
))}
</ul>
</div>
);
}Activity Detection:
- Web Platform: Monitors mouse movement, clicks, keyboard, scrolling, tab visibility
- React Native: Monitors AppState changes (foreground/background)
- Throttled: Maximum 1 status update per second for performance
- Configurable: Customize inactivity timeout and check intervals
Real-time Log Streaming
Stream application logs, API requests, database queries, and system metrics in real-time with powerful filtering capabilities.
Available Log Hubs:
- Application Logs - General application logs (errors, warnings, information)
- API Logs - HTTP request/response logs with performance metrics
- Query Logs - Database query performance and slow query tracking
- Dashboard - Aggregated statistics and system health metrics
Features:
- Filter-Based Subscription - Subscribe only to relevant logs (by service, level, duration, etc.)
- Buffer Management - Configurable in-memory buffer with FIFO eviction
- Auto-Load Recent - Optionally load historical logs on subscription
- Correlation Tracing - Track all logs related to a single request by correlation ID
- Manual Connection - Connect/disconnect explicitly or with auto-connect option
import {
useApplicationLogs,
useApiLogs,
useQueryLogs,
useDashboard,
} from '@actschurch/ccms-sdk/realtime/logs';
// Application logs with filtering and event handling
function LogsViewer() {
const {
logs,
isConnected,
isSubscribed,
error,
connect,
disconnect,
subscribe,
unsubscribe,
clearLogs,
loadRecent,
} = useApplicationLogs({
autoConnect: true,
filter: {
serviceNames: ['CCMS.API', 'CCMS.Tasks'],
logLevels: ['Error', 'Warning', 'Critical'],
userId: currentUser?.id, // Filter by user
},
maxBufferSize: 1000, // Keep last 1000 logs
autoLoadRecent: true, // Load recent on subscribe
recentLogsLimit: 100, // Load 100 recent logs
onLog: (log) => {
// Handle new log in real-time
if (log.level === 'Critical') {
showNotification({ title: 'Critical Error', message: log.message });
}
},
});
useEffect(() => {
subscribe();
return () => disconnect();
}, []);
return (
<div>
<div className="status">
Status: {isConnected ? '🟢 Connected' : '🔴 Disconnected'}
{isSubscribed && ' (Subscribed)'}
</div>
<button onClick={clearLogs}>Clear Logs</button>
<table>
<thead>
<tr>
<th>Time</th>
<th>Level</th>
<th>Service</th>
<th>Message</th>
</tr>
</thead>
<tbody>
{logs.map((log) => (
<tr key={log.id} className={`log-${log.level.toLowerCase()}`}>
<td>{new Date(log.timestamp).toLocaleString()}</td>
<td>{log.level}</td>
<td>{log.serviceName}</td>
<td>{log.message}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
// API request logs - track slow or failed requests
function ApiLogsMonitor() {
const { logs } = useApiLogs({
autoConnect: true,
filter: {
minDurationMs: 1000, // Only slow requests (>1s)
statusCodes: [400, 404, 500, 502, 503], // Error codes
pathFilter: '/api/', // Path pattern
},
});
return (
<div>
<h3>Slow & Failed API Requests</h3>
{logs.map(log => (
<div key={log.id}>
<span>{log.httpMethod} {log.path}</span>
<span>Status: {log.statusCode}</span>
<span>Duration: {log.durationMs}ms</span>
</div>
))}
</div>
);
}
// Query performance logs - track slow database queries
function QueryPerformanceMonitor() {
const { logs } = useQueryLogs({
filter: {
slowOnly: true, // Only marked as slow
minDurationMs: 500, // >500ms
queryTypes: ['SELECT'], // Only SELECT queries
},
});
return (
<div>
<h3>Slow Database Queries</h3>
{logs.map(log => (
<div key={log.id}>
<span>{log.queryType} - {log.entityType}</span>
<span>Duration: {log.durationMs}ms</span>
<span>Rows: {log.rowCount}</span>
</div>
))}
</div>
);
}
// System dashboard with real-time statistics
function PerformanceDashboard() {
const {
stats,
isConnected,
refreshStats,
getLogsByCorrelationId,
getRecentErrors,
startAutoRefresh,
stopAutoRefresh,
} = useDashboard({
autoConnect: true,
refreshInterval: 5000, // Auto-refresh every 5s
onUpdate: (stats) => {
console.log('Dashboard updated:', stats);
},
});
useEffect(() => {
startAutoRefresh();
return () => stopAutoRefresh();
}, []);
const handleCorrelationTrace = async (correlationId: string) => {
const trace = await getLogsByCorrelationId(correlationId);
// trace.applicationLogs, trace.apiLogs, trace.queryLogs
console.log('Full request trace:', trace);
};
return (
<div>
<h2>System Health Dashboard</h2>
<div className="grid grid-cols-3 gap-4">
<MetricCard
title="Avg Response Time"
value={`${stats?.averageResponseTime.toFixed(2)}ms`}
/>
<MetricCard
title="Error Rate"
value={`${((stats?.errorRequests / stats?.totalApiRequests) * 100).toFixed(2)}%`}
alert={stats?.errorRequests > 10}
/>
<MetricCard
title="Slow Queries"
value={stats?.slowQueries}
/>
<MetricCard
title="Active Services"
value={stats?.activeServices.length}
/>
<MetricCard
title="Logs/Minute"
value={stats?.logsPerMinute}
/>
<MetricCard
title="Total Errors"
value={stats?.errorCount}
/>
</div>
<button onClick={refreshStats}>Refresh Now</button>
</div>
);
}Log Entry Structures:
- ApplicationLogEntry: timestamp, level, category, message, exception, correlationId, serviceName, properties
- ApiRequestLogEntry: httpMethod, path, statusCode, durationMs, requestBody, responseBody, headers
- QueryPerformanceLogEntry: queryType, entityType, queryText, durationMs, rowCount, isSlowQuery
- DashboardStats: Aggregated metrics including averages, counts, and active services
Migration from Legacy RealtimeClient
The old RealtimeClient is deprecated. Migrate to the new SignalR-based modules:
// Old (deprecated)
import { RealtimeClient } from '@actschurch/ccms-sdk';
const realtime = new RealtimeClient(config);
realtime.updatePresence('Online');
// New (recommended)
import { usePresence } from '@actschurch/ccms-sdk/realtime/presence';
const { updateStatus } = usePresence();
updateStatus(PresenceStatus.Online);Error Handling
The SDK provides comprehensive error handling utilities.
import { ErrorHandler, CCMSError } from '@actschurch/ccms-sdk';
// Create error handler
const errorHandler = new ErrorHandler({
onError: (error) => {
// Global error handling
console.error('Error:', error.message);
},
displayMode: 'toast', // 'toast' | 'modal' | 'none'
});
// Handle errors
try {
await someOperation();
} catch (error) {
errorHandler.handle(error);
}
// Custom error class
throw new CCMSError('Something went wrong', {
code: 'VALIDATION_ERROR',
statusCode: 400,
details: { field: 'email' },
});React Integration
Provider Setup
Wrap your application with CCMSProvider:
import { CCMSProvider } from '@actschurch/ccms-sdk';
function App() {
return (
<CCMSProvider
config={{
baseUrl: 'https://api.yourccms.com',
enableRealtime: true,
realtimeUrl: 'wss://api.yourccms.com', // Optional
}}
authConfig={{
autoRefresh: true,
refreshThresholdSeconds: 60,
}}
>
<YourApp />
</CCMSProvider>
);
}Hooks
Core Hooks
import {
useCCMS,
useAuth,
useHttpClient,
useRealtime,
usePermissions,
} from '@actschurch/ccms-sdk';
function MyComponent() {
// Access full SDK context
const { http, auth, realtime, permissions } = useCCMS();
// Or use specific hooks
const httpClient = useHttpClient();
const realtimeClient = useRealtime();
const permissionManager = usePermissions();
}Authentication Hooks
import { useAuth, useIsAuthenticated, useUser, useHasRole, useHasRight } from '@actschurch/ccms-sdk';
function Profile() {
const { user, isAuthenticated, isLoading, login, logout } = useAuth();
// Or use individual hooks
const isLoggedIn = useIsAuthenticated();
const currentUser = useUser();
const isAdmin = useHasRole('admin');
const canEditMembers = useHasRight('members.edit');
if (isLoading) return <Loading />;
if (!isAuthenticated) return <LoginForm />;
return (
<div>
<h1>Welcome, {user?.firstName}</h1>
{isAdmin && <AdminPanel />}
{canEditMembers && <EditButton />}
</div>
);
}API Hooks
import { useQuery, useMutation, useInfiniteQuery, usePrefetch } from '@actschurch/ccms-sdk';
function MemberList() {
// Fetch data
const {
data: members,
isLoading,
error,
refetch,
} = useQuery<Member[]>('/api/members', {
enabled: true,
refetchOnFocus: true,
});
// Mutations
const { mutate: createMember, isLoading: isCreating } = useMutation<Member>(
'/api/members',
'POST',
{
onSuccess: (member) => {
console.log('Created:', member);
refetch();
},
onError: (error) => console.error(error),
}
);
// Infinite scrolling
const {
pages,
fetchNextPage,
hasNextPage,
isFetchingNextPage,
} = useInfiniteQuery<Member>('/api/members', undefined, {
pageSize: 20,
});
// Prefetch for navigation
const { prefetch } = usePrefetch();
const handleHover = (memberId: string) => {
prefetch<Member>(`/api/members/${memberId}`);
};
}Realtime Hooks
Presence Hooks
import {
usePresence,
usePresenceStatus,
useOnlineUsers,
useUserPresence,
} from '@actschurch/ccms-sdk/realtime/presence';
function ChatRoom() {
// Main presence hook
const { state, updateStatus, getUserPresence, getAllPresence } = usePresence();
// Get current user's status
const myStatus = usePresenceStatus(); // 'Online' | 'Away' | 'Busy' | 'Offline'
// Get all online users
const onlineUsers = useOnlineUsers(); // UserPresenceUpdate[]
// Get specific user's presence
const userPresence = useUserPresence('user-123');
useEffect(() => {
updateStatus('Online', 'In chat room');
return () => updateStatus('Offline');
}, []);
return (
<div>
<p>Your status: {myStatus}</p>
<p>Online users: {onlineUsers.length}</p>
{userPresence && <span>{userPresence.status}</span>}
</div>
);
}Log Streaming Hooks
import {
useApplicationLogs,
useApiLogs,
useQueryLogs,
useDashboard,
} from '@actschurch/ccms-sdk/realtime/logs';
function LogMonitor() {
// Application logs
const {
logs: appLogs,
isConnected,
subscribe,
clearLogs,
loadRecent,
} = useApplicationLogs({
autoConnect: true,
filter: { logLevels: ['Error', 'Critical'] },
maxBufferSize: 1000,
});
// API request logs
const { logs: apiLogs } = useApiLogs({
filter: { minDurationMs: 1000 }, // Slow requests only
});
// Database query logs
const { logs: queryLogs } = useQueryLogs({
filter: { slowOnly: true },
});
// Dashboard statistics
const { stats, refreshStats, getLogsByCorrelationId } = useDashboard({
autoConnect: true,
refreshInterval: 5000,
});
return (/* ... */);
}Legacy Realtime Hooks (Deprecated)
// ⚠️ DEPRECATED: These hooks are deprecated and will be removed in v2.0.0
// Use the new hooks above instead
import { useRealtimeEvent, useConnectionState } from '@actschurch/ccms-sdk';
function OldComponent() {
const connectionState = useConnectionState(); // Use usePresence() instead
useRealtimeEvent('event', handler); // Use specific hooks instead
}Utility Hooks
import {
useDebounce,
useThrottle,
usePrevious,
useStorage,
useNetworkStatus,
useToggle,
useCounter,
useArray,
useMap,
useInterval,
useTimeout,
useMediaQuery,
useClipboard,
useClickOutside,
useKeyPress,
} from '@actschurch/ccms-sdk';
function SearchComponent() {
const [search, setSearch] = useState('');
const debouncedSearch = useDebounce(search, 300);
// Network status
const { isOnline, wasOffline } = useNetworkStatus();
// Persistent storage (cross-platform)
const [theme, setTheme] = useStorage('theme', 'light');
// Boolean toggle
const [isOpen, toggle] = useToggle(false);
// Counter with limits
const { count, increment, decrement } = useCounter(0, { min: 0, max: 100 });
// Array operations
const { array, push, remove, clear } = useArray<string>([]);
// Media queries
const isMobile = useMediaQuery('(max-width: 768px)');
// Clipboard
const { copy, copied } = useClipboard();
// Click outside detection
const ref = useClickOutside<HTMLDivElement>(() => setIsOpen(false));
// Keyboard shortcuts
useKeyPress('k', () => openSearch(), { meta: true }); // Cmd+K
}Components
Permission Components
import { Can, RequireAuth, RequireRole, RequireRight } from '@actschurch/ccms-sdk';
function App() {
return (
<RequireAuth fallback={<LoginPage />}>
<Dashboard />
</RequireAuth>
);
}
function Dashboard() {
return (
<div>
{/* Feature-based access */}
<Can feature="members.view">
<MemberList />
</Can>
{/* Role-based access */}
<RequireRole role="admin" fallback={<AccessDenied />}>
<AdminPanel />
</RequireRole>
{/* Multiple roles (any) */}
<RequireRole roles={['admin', 'staff']} requireAll={false}>
<StaffTools />
</RequireRole>
{/* Right-based access */}
<RequireRight right="reports.view">
<Reports />
</RequireRight>
</div>
);
}Error Boundary
import { ErrorBoundary } from '@actschurch/ccms-sdk';
function App() {
return (
<ErrorBoundary
fallback={({ error, reset }) => (
<div>
<h1>Something went wrong</h1>
<p>{error.message}</p>
<button onClick={reset}>Try Again</button>
</div>
)}
>
<MyApp />
</ErrorBoundary>
);
}React Native Setup
Configure Global Storage
// In your app entry point (App.tsx or index.js)
import AsyncStorage from '@react-native-async-storage/async-storage';
import NetInfo from '@react-native-community/netinfo';
import { setGlobalStorage, setGlobalNetworkStatus } from '@actschurch/ccms-sdk';
// Configure storage (do this before using any SDK features)
setGlobalStorage(AsyncStorage);
// Configure network status detection
setGlobalNetworkStatus({
isOnline: async () => {
const state = await NetInfo.fetch();
return state.isConnected ?? false;
},
subscribe: (callback) => {
return NetInfo.addEventListener((state) => {
callback(state.isConnected ?? false);
});
},
});Use with Expo SecureStore
import * as SecureStore from 'expo-secure-store';
import { SecureStorageAdapter, AuthManager } from '@actschurch/ccms-sdk';
const authManager = new AuthManager(http, {
storage: new SecureStorageAdapter(SecureStore),
});Services
The SDK provides pre-built service classes that encapsulate common API operations for each domain. Services handle request formatting, response parsing, and provide a clean interface for interacting with the CCMS backend.
Available Service Modules
| Module | Services | Key Services | |--------|----------|--------------| | Task Management | 12 services | TaskService, TaskStatusService, TaskPriorityService, TaskProgressStageService, TaskAssignmentService, TaskAttachmentService, TaskCommentService, TaskNoteService, TaskLogService, LogTypeService, TaskNotificationService, TaskNotificationQueueService | | User Management | 9 services | UserService, RoleService, RightService, AuthService, AuditService, AdminService, SystemService, UserPreferencesService, UserPushDeviceService | | Payments | 14 services | PaymentTransactionService, PayerService, PaymentMethodService, TransactionStatusService, TransactionCategoryService, TransactionRefundService, RefundStatusService, BillingAgreementService, RecurringTransactionService, SettlementService, SettlementLineService, PaymentIpnEventService, PaymentNotificationQueueService, PayFastWebhookService | | Procurement | 18 services | PurchaseRequestService, QuotationService, InvoiceService, RequestAttachmentService, RequestCommentService, RequestTypeService, RequestStatusService, RequestStageService, QuotationStatusService, InvoiceStatusService, ProcurementRoleTypeService, NotificationService, AuditLogService, QuotationLineService, InvoiceLineService, RequestApprovalStatusService, SagePurchaseOrderService, SageItemService | | Projects | 17 services | ProjectService, ProjectStatusService, ProjectTypeService, ProjectAuditLogService, ProjectMessageService, ProjectMilestoneService, ProjectMilestoneTaskService, ProjectRiskService, ProjectTeamMemberService, TaskTimeLogService, ProjectResourceService, ProjectDocumentService, PlannedBudgetItemService, TaskDependencyService, ResourceTypeService, ProjectRoleService, BudgetLineItemService | | Orders | 6 services | OrderService, OrderLineService, OrderPaymentService, OrderStatusService, PaymentStatusService, OrderNotificationService | | Meetings | 14 services | MeetingService, MeetingStatusService, MeetingTypeService, MeetingVenueService, MeetingAttendeeService, MeetingAttendanceStatusService, MeetingSetupService, MeetingRequestService, MeetingCommentService, MeetingFileService, SetupInMeetingService, RequestInMeetingService, LocationVenueRequestService, LocationVenueSetupService | | Members | 9 services | MemberService, FamilyService, MemberTypeService, MaritalStatusService, MemberAddressService, MemberLocationService, AllergyService, DisabilityService, RelationshipService | | HR | 19 services | EmployeeService, LeaveService, DutyService, EmployeeDutyService, EmployeeFileCategoryService, EmployeeFileTypeService, EmployeeFileService, EmployeeStatusService, EmployeeTypeService, LeaveDocumentTypeService, LeaveDocumentService, LeaveDutyService, LeaveNotificationQueueService, LeaveStatusService, LeaveTypeService, PolicyService, PolicyCategoryService, PolicySignatureService | | Departments | 10 services | DepartmentService, DesignationService, DesignationTaskService, MemberDesignationService, MemberInDepartmentService, MinistryService, MinistryActivityService, MinistryEquipmentService, MinistryRoleService, MinistryTeamService | | Communication | 6 services | EmailService, SmsService, PushNotificationService, WhatsAppService, TemplateService, DeviceService | | File Management | 2 services | FileService, MultipartUploadService | | Locations | 8 services | LocationService, AddressService, LocationInfoService, LocationLeaderService, LocationSocialMediaService, LocationVenueService, ServiceTimeService, SocialMediaService | | Products | 8 services | ProductService, ProductTypeService, ProductColorService, ProductSizeService, ProductImageService, ProductStockService, ProductTransactionService, TransactionTypeService | | Suppliers | 4 services | SupplierService, SupplierCategoryService, SupplierContactService, SupplierNoteService | | Resources | 8 services | CourseService, CourseCategoryService, CourseSessionService, UsageLogService, CourseStatusService, CourseCategoryStatusService, CourseSessionStatusService, CourseSessionTypeService | | Feedback | 5 services | FeedbackService, FeedbackCategoryService, FeedbackTypeService, FeedbackCategoryRecipientService, FeedbackNotificationQueueService | | System | 10 services | SystemService, ApiRequestLogService, QueryPerformanceLogService, LogsService, HealthService, ServicesService, RabbitMQManagementService, RedisManagementService, RabbitMQTestService, RedisTestService | | Generators | 4 services | BarcodeService, QrCodeService, UtilityCodeService, GeneratedCodeService |
For detailed information about the service architecture and how to create custom services, see Services Module Documentation.
Using Services
import { MemberService, TaskService } from '@actschurch/ccms-sdk';
// Initialize services with HTTP client
const memberService = new MemberService(http);
const taskService = new TaskService(http);
// Member operations
const members = await memberService.getAll({ page: 1, pageSize: 20 });
const member = await memberService.getById('member-123');
const newMember = await memberService.create({
firstName: 'John',
lastName: 'Doe',
email: '[email protected]',
});
await memberService.update('member-123', { phone: '+1234567890' });
await memberService.delete('member-123');
// Search members
const searchResults = await memberService.search({
query: 'John',
filters: { status: 'active', memberType: 'regular' },
sort: { field: 'lastName', direction: 'asc' },
});
// Task operations
const tasks = await taskService.getMyTasks();
const task = await taskService.create({
title: 'Follow up with new member',
description: 'Welcome call and orientation',
assignedTo: ['user-456'],
dueDate: '2024-02-01',
priority: 'high',
});
await taskService.updateStatus('task-789', 'completed');
await taskService.addComment('task-789', 'Completed the follow-up call');Service with React Hooks
The SDK provides dedicated hooks for each service module for seamless React integration:
import {
useTaskServices,
useUsersServices,
useMembersServices,
useMeetingsServices,
useLocationsServices,
useFileServices,
useCommunicationServices,
useSupplierServices,
useResourcesServices,
useProjectsServices,
useProcurementsServices,
useProductsServices,
usePaymentServices,
useOrderServices,
useHrServices,
useDepartmentsServices,
useFeedbackServices,
useSystemServices,
useGeneratorsServices,
} from '@actschurch/ccms-sdk';
function TaskList() {
const { task, taskStatus, taskPriority } = useTaskServices();
const [tasks, setTasks] = useState<Task[]>([]);
useEffect(() => {
task.getAll().then(setTasks);
}, []);
const handleCreate = async (data: CreateTaskRequest) => {
const newTask = await task.create(data);
setTasks(prev => [...prev, newTask]);
};
return (/* ... */);
}
// Access multiple services in one module
function CommunicationDashboard() {
const { email, sms, pushNotification, whatsApp } = useCommunicationServices();
const sendMultiChannelNotification = async (message: string, recipients: string[]) => {
await Promise.all([
email.send({ to: recipients, subject: 'Notification', body: message }),
sms.send({ to: recipients, message }),
pushNotification.send({ userIds: recipients, title: 'Alert', body: message }),
]);
};
return (/* ... */);
}
// Use meeting services
function MeetingScheduler() {
const { meeting, meetingAttendee, meetingVenue } = useMeetingsServices();
const createMeeting = async (data: MeetingRequest) => {
const newMeeting = await meeting.create(data);
await meetingAttendee.addAttendees(newMeeting.id, data.attendeeIds);
return newMeeting;
};
return (/* ... */);
}Custom Service Creation
You can create custom services by extending the base service class:
import { BaseService } from '@actschurch/ccms-sdk';
class CustomService extends BaseService {
constructor(http: HttpClient) {
super(http, '/api/custom');
}
async getCustomData(id: string): Promise<CustomData> {
const response = await this.http.get<CustomData>(`${this.basePath}/${id}`);
return response.data!;
}
async performCustomAction(data: ActionRequest): Promise<ActionResult> {
const response = await this.http.post<ActionResult>(
`${this.basePath}/action`,
data
);
return response.data!;
}
}Service Configuration
Services can be configured with default options:
const memberService = new MemberService(http, {
// Default pagination
defaultPageSize: 50,
// Cache configuration
cacheEnabled: true,
cacheTTL: 5 * 60 * 1000, // 5 minutes
// Retry configuration
retryOnError: true,
maxRetries: 3,
});Batch Operations
Services support batch operations for efficiency:
// Batch create
const members = await memberService.createMany([
{ firstName: 'John', lastName: 'Doe' },
{ firstName: 'Jane', lastName: 'Smith' },
]);
// Batch update
await memberService.updateMany([
{ id: 'member-1', status: 'active' },
{ id: 'member-2', status: 'active' },
]);
// Batch delete
await memberService.deleteMany(['member-3', 'member-4']);Service Events
Services emit events for tracking operations:
memberService.on('created', (member) => {
console.log('Member created:', member.id);
analytics.track('member_created', { memberId: member.id });
});
memberService.on('updated', (member) => {
console.log('Member updated:', member.id);
});
memberService.on('deleted', (id) => {
console.log('Member deleted:', id);
});
memberService.on('error', (error, operation) => {
console.error(`Error during ${operation}:`, error);
});Utilities
The SDK includes comprehensive cross-platform utilities:
String Utilities
import {
capitalize,
toCamelCase,
toKebabCase,
toSnakeCase,
toPascalCase,
slugify,
truncate,
mask,
getInitials,
pluralize,
similarity,
} from '@actschurch/ccms-sdk';
capitalize('hello world'); // "Hello world"
toCamelCase('hello-world'); // "helloWorld"
slugify('Hello World!'); // "hello-world"
truncate('Long text...', 10); // "Long te..."
mask('1234567890', 4); // "******7890"
getInitials('John Doe'); // "JD"
pluralize('item', 5); // "items"
similarity('hello', 'hallo'); // 0.8Number Utilities
import {
formatCurrency,
formatNumber,
formatPercentage,
humanizeNumber,
round,
clamp,
percentage,
toOrdinal,
formatFileSize,
formatDurationFromSeconds,
} from '@actschurch/ccms-sdk';
formatCurrency(1234.56, 'USD'); // "$1,234.56"
formatNumber(1234567); // "1,234,567"
formatPercentage(0.456); // "45.60%"
humanizeNumber(1500000); // "1.5M"
round(3.14159, 2); // 3.14
clamp(150, 0, 100); // 100
toOrdinal(1); // "1st"
formatFileSize(1536); // "1.50 KB"
formatDurationFromSeconds(3661); // "1:01:01"Date/Time Utilities
import {
formatDate,
parseDate,
addDays,
addMonths,
differenceInDays,
startOfDay,
endOfDay,
isWeekend,
humanize,
fromNow,
toUnix,
fromUnix,
} from '@actschurch/ccms-sdk';
formatDate(new Date(), 'YYYY-MM-DD'); // "2024-01-15"
addDays(new Date(), 7); // Date 7 days from now
differenceInDays(date1, date2); // Number of days between
humanize(pastDate); // "2 hours ago"
isWeekend(new Date()); // true/falseArray Utilities
import {
unique,
uniqueBy,
chunk,
sortBy,
groupBy,
partition,
shuffle,
sample,
intersection,
difference,
union,
flatten,
moveItem,
} from '@actschurch/ccms-sdk';
unique([1, 2, 2, 3]); // [1, 2, 3]
uniqueBy(users, 'email'); // Remove duplicates by email
chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]
sortBy(users, 'lastName', 'asc');
groupBy(users, 'department'); // { IT: [...], HR: [...] }
partition(numbers, n => n > 5); // [[6, 7, 8], [1, 2, 3]]
shuffle([1, 2, 3, 4, 5]); // Random order
sample(items, 3); // Random 3 itemsObject Utilities
import {
deepClone,
deepMerge,
get,
set,
pick,
omit,
flattenObject,
unflattenObject,
deepEqual,
diff,
isEmpty,
mapValues,
filterObject,
} from '@actschurch/ccms-sdk';
deepClone(complexObject);
deepMerge(defaults, userConfig);
get(obj, 'user.address.city', 'Unknown');
set(obj, 'user.address.city', 'New York');
pick(user, ['id', 'name', 'email']);
omit(user, ['password', 'secretKey']);
flattenObject({ a: { b: 1 } }); // { 'a.b': 1 }
deepEqual(obj1, obj2); // true/false
diff(original, modified); // { changed: 'fields' }Validation Utilities
import {
isEmail,
isPhoneNumber,
isUrl,
isUUID,
isStrongPassword,
getPasswordStrength,
isCreditCard,
getCreditCardType,
isIPv4,
isIPv6,
validateEmail,
validatePassword,
validateUsername,
validateAll,
} from '@actschurch/ccms-sdk';
isEmail('[email protected]'); // true
isPhoneNumber('+1-555-123-4567'); // true
isStrongPassword('MyP@ss123!'); // true
getPasswordStrength('weak'); // { score: 1, level: 'weak', suggestions: [...] }
isCreditCard('4111111111111111'); // true (Luhn check)
getCreditCardType('4111...'); // 'visa'
// Detailed validation
validateEmail('invalid'); // { valid: false, error: 'Invalid email format' }
validatePassword('weak', { minLength: 8, requireSpecial: true });
// Multiple validations
validateAll([
() => validateEmail(email),
() => validatePassword(password),
() => validateRequired(name, 'Name'),
]); // { valid: false, errors: ['...', '...'] }Color Utilities
import {
hexToRgb,
rgbToHex,
hexToHsl,
lighten,
darken,
getContrastColor,
isLightColor,
mix,
generatePalette,
} from '@actschurch/ccms-sdk';
hexToRgb('#ff5500'); // { r: 255, g: 85, b: 0 }
rgbToHex(255, 85, 0); // "#ff5500"
lighten('#ff5500', 0.2); // Lighter version
darken('#ff5500', 0.2); // Darker version
getContrastColor('#ff5500'); // '#ffffff' or '#000000'
mix('#ff0000', '#0000ff', 0.5); // Purple
generatePalette('#ff5500', 5); // { light: [...], dark: [...] }Environment Utilities
import {
getEnv,
isProduction,
isDevelopment,
isBrowser,
isReactNative,
isNode,
getPlatform,
isMobile,
isIOS,
isAndroid,
getBrowserInfo,
} from '@actschurch/ccms-sdk';
if (isProduction()) {
// Production-only code
}
if (isReactNative()) {
// React Native specific code
}
if (isMobile()) {
// Mobile-specific UI
}
const platform = getPlatform(); // 'ios' | 'android' | 'web' | 'node' | 'unknown'Device Utilities
import {
getScreenInfo,
getDeviceType,
getOrientation,
hasTouch,
hasGeolocation,
hasNotifications,
prefersDarkMode,
prefersReducedMotion,
getPreferredLanguage,
getTimezone,
isOnline,
getConnectionType,
getCurrentBreakpoint,
isAtLeast,
isAtMost,
} from '@actschurch/ccms-sdk';
const screen = getScreenInfo(); // { width, height, pixelRatio, orientation }
const device = getDeviceType(); // 'phone' | 'tablet' | 'desktop'
const orientation = getOrientation(); // 'portrait' | 'landscape'
if (prefersDarkMode()) {
// Apply dark theme
}
const breakpoint = getCurrentBreakpoint(); // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
if (isAtLeast('md')) {
// Tablet and above
}API Response Helpers
import {
createSuccessResponse,
createErrorResponse,
createPaginatedResponse,
isSuccessResponse,
unwrapResponse,
safeUnwrap,
mapResponse,
paginateArray,
isSuccessStatus,
getStatusMessage,
fetchWithRetry,
createQueryString,
buildUrl,
} from '@actschurch/ccms-sdk';
// Create responses
const success = createSuccessResponse(data, 'Operation successful');
const error = createErrorResponse('Validation failed', ['Email is required']);
const paginated = createPaginatedResponse(items, { page: 1, pageSize: 20, totalItems: 100 });
// Check and unwrap
if (isSuccessResponse(response)) {
const data = unwrapResponse(response);
}
// Safe unwrap with fallback
const users = safeUnwrap(response, []);
// Retry failed requests
const result = await fetchWithRetry(
() => fetch('/api/data'),
{ maxRetries: 3, retryDelay: 1000, backoff: 'exponential' }
);
// Build URLs
const url = buildUrl('https://api.example.com', '/users', { page: 1, limit: 20 });
// "https://api.example.com/users?page=1&limit=20"Error Utilities
import {
safeTry,
safeTryAsync,
toErrorMessage,
normalizeError,
isNetworkError,
isTimeoutError,
isAbortError,
retryOnError,
createErrorBoundary,
assert,
assertDefined,
formatErrorForUser,
ValidationError,
NetworkError,
TimeoutError,
} from '@actschurch/ccms-sdk';
// Safe execution with fallback
const result = safeTry(() => JSON.parse(input), {});
// Async safe execution
const data = await safeTryAsync(() => fetchData(), defaultData);
// Error classification
if (isNetworkError(error)) {
showOfflineMessage();
} else if (isTimeoutError(error)) {
showTimeoutMessage();
}
// Retry with configuration
await retryOnError(fetchData, {
maxRetries: 3,
delayMs: 1000,
shouldRetry: (error, attempt) => attempt < 3 && isNetworkError(error),
});
// Custom error classes
throw new ValidationError('Invalid input', { code: 'VALIDATION_ERROR' });
// User-friendly messages
const message = formatErrorForUser(error);
// "Unable to connect. Please check your internet connection."Models
The SDK includes TypeScript models for all CCMS entities:
import {
// Identity
LoggedOnUser,
UserModelView,
RoleModelView,
// Members
Member,
MemberModelView,
MemberType,
Family,
// Tasks
Task,
TaskModelView,
TaskStatus,
TaskPriority,
TaskAssignment,
// Departments
Department,
Ministry,
Designation,
// Locations
Location,
Address,
// And many more...
} from '@actschurch/ccms-sdk';Testing
The SDK includes testing utilities for mocking:
import {
MockHttpClient,
MockAuthManager,
MockRealtimeClient,
MockPermissionManager,
createMockUser,
createMockPagedResult,
TestProvider,
} from '@actschurch/ccms-sdk/testing';
// In your tests
describe('MyComponent', () => {
it('renders member list', async () => {
const mockHttp = new MockHttpClient();
mockHttp.onGet('/api/members').reply(200, [
{ id: '1', firstName: 'John' },
{ id: '2', firstName: 'Jane' },
]);
render(
<TestProvider http={mockHttp}>
<MemberList />
</TestProvider>
);
await waitFor(() => {
expect(screen.getByText('John')).toBeInTheDocument();
});
});
});
// Create mock data
const mockUser = createMockUser({
firstName: 'Test',
roles: ['admin'],
});
const mockPaged = createMockPagedResult([item1, item2], {
page: 1,
pageSize: 20,
totalItems: 100,
});API Reference
Core Classes
| Class | Description |
|-------|-------------|
| HttpClient | HTTP client for API requests with interceptors and retry logic |
| AuthManager | Authentication state management with automatic token refresh |
| PermissionManager | Role-based and feature-based access control |
| PresenceClient | SignalR presence tracking hub client |
| ApplicationLogsClient | SignalR application logs streaming client |
| ApiLogsClient | SignalR API request logs streaming client |
| QueryLogsClient | SignalR database query logs streaming client |
| DashboardClient | SignalR dashboard statistics client |
| ErrorHandler | Global error handling with custom error types |
| ~~RealtimeClient~~ | ⚠️ Deprecated - Use SignalR-based clients instead |
React Hooks
Core Hooks
| Hook | Description |
|------|-------------|
| useCCMS() | Access full SDK context |
| useAuth() | Authentication state and actions |
| useHttpClient() | HTTP client instance |
| usePermissions() | Permission manager instance |
API Hooks
| Hook | Description |
|------|-------------|
| useQuery() | Data fetching with caching |
| useMutation() | Data mutations |
| useInfiniteQuery() | Paginated/infinite data |
| usePrefetch() | Prefetch data for navigation |
Service Hooks
| Hook | Services | Description |
|------|----------|-------------|
| useTaskServices() | 12 | Task, TaskStatus, TaskPriority, TaskAssignment, TaskComment, TaskNotification, etc. |
| useUsersServices() | 9 | User, Role, Right, Auth, Audit, Admin, System, UserPreferences, UserPushDevice |
| useMembersServices() | 9 | Member, Family, MemberType, MaritalStatus, MemberAddress, Allergy, Disability, etc. |
| useMeetingsServices() | 14 | Meeting, MeetingStatus, MeetingType, MeetingVenue, MeetingAttendee, MeetingSetup, etc. |
| useLocationsServices() | 8 | Location, Address, LocationInfo, LocationLeader, LocationVenue, ServiceTime, etc. |
| useFileServices() | 2 | File, MultipartUpload |
| useCommunicationServices() | 6 | Email, Sms, PushNotification, WhatsApp, Template, Device |
| useSupplierServices() | 4 | Supplier, SupplierCategory, SupplierContact, SupplierNote |
| useResourcesServices() | 8 | Course, CourseCategory, CourseSession, UsageLog, CourseStatus, etc. |
| useProjectsServices() | 17 | Project, ProjectStatus, ProjectMilestone, ProjectTeamMember, TaskTimeLog, etc. |
| useProcurementsServices() | 18 | PurchaseRequest, Quotation, Invoice, RequestAttachment, SagePurchaseOrder, etc. |
| useProductsServices() | 8 | Product, ProductType, ProductColor, ProductSize, ProductStock, etc. |
| usePaymentServices() | 14 | PaymentTransaction, Payer, Settlement, Refund, BillingAgreement, PayFast, etc. |
| useOrderServices() | 6 | Order, OrderLine, OrderPayment, OrderStatus, PaymentStatus, OrderNotification |
| useHrServices() | 19 | Employee, Leave, Duty, EmployeeFile, LeaveDocument, Policy, etc. |
| useDepartmentsServices() | 10 | Department, Designation, Ministry, MinistryActivity, MinistryRole, etc. |
| useFeedbackServices() | 5 | Feedback, FeedbackCategory, FeedbackType, FeedbackNotification, etc. |
| useSystemServices() | 10 | System, ApiRequestLog, QueryPerformanceLog, Health, RabbitMQ, Redis, etc. |
| useGeneratorsServices() | 4 | Barcode, QrCode, UtilityCode, GeneratedCode |
Realtime Hooks - Presence (4 hooks)
| Hook | Return Type | Description |
|------|-------------|-------------|
| usePresence() | { state, updateStatus, getUserPresence, getOnlineUsers, getAllPresence } | Main presence hook with full state and methods |
| usePresenceStatus() | PresenceStatus | Get current user's presence status (Online/Away/Busy/Offline) |
| useOnlineUsers() | UserPresenceUpdate[] | Get array of all currently online users |
| useUserPresence(userId) | UserPresenceUpdate \| null | Get specific user's real-time presence information |
Presence State includes: isConnected, currentUserPresence, onlineUsers (Map), connectionError
Realtime Hooks - Logs (4 hooks)
| Hook | Return Type | Description |
|------|-------------|-------------|
| useApplicationLogs(options) | { logs, isConnected, subscribe, unsubscribe, clearLogs, loadRecent, ... } | Stream application logs with filtering (errors, warnings, info) |
| useApiLogs(options) | { logs, isConnected, subscribe, unsubscribe, ... } | Stream API request logs (HTTP requests, responses, performance) |
| useQueryLogs(options) | { logs, isConnected, subscribe, unsubscribe, ... } | Stream database query logs (query performance, slow queries) |
| useDashboard(options) | { stats, refreshStats, getLogsByCorrelationId, getRecentErrors, ... } | Real-time system statistics and aggregated metrics |
Common Options: autoConnect, filter (serviceNames, logLevels, etc.), maxBufferSize, autoLoadRecent, onLog
Utility Hooks
| Hook | Description |
|------|-------------|
| useDebounce() | Debounced values |
| useThrottle() | Throttled values |
| usePrevious() | Previous value tracking |
| useStorage() | Cross-platform storage |
| useNetworkStatus() | Online/offline detection |
| useToggle() | Boolean state toggle |
| useCounter() | Counter with min/max |
| useArray() | Array state operations |
| useMap() | Map state operations |
| useInterval() | Declarative intervals |
| useTimeout() | Declarative timeouts |
| useMediaQuery() | Responsive media queries |
| useClipboard() | Clipboard operations |
| useClickOutside() | Click outside detection |
| useKeyPress() | Keyboard shortcuts |
Upload Hooks
| Hook | Description |
|------|-------------|
| useFileUpload() | File upload with progress |
| useMultipartUpload() | Large file multipart upload |
React Components
| Component | Description |
|-----------|-------------|
| CCMSProvider | Root provider component |
| Can | Feature-based rendering |
| RequireAuth | Authentication guard |
| RequireRole | Role-based rendering |
| RequireRight | Permission-based rendering |
| ErrorBoundary | Error boundary with fallback |
Deprecation Notices
Legacy Realtime Module
The original RealtimeClient and related hooks are deprecated and will be removed in version 2.0.0.
Deprecated APIs
RealtimeClientclassuseConnectionState()hookuseRealtimeConnection()hookuseRealtimeEvent()hookuseRealtimeMessage()hookuseRealtimeSend()hookuseRealtimeGroup()hook- Legacy
usePresence()hook
Migration Path
| Old API | New API | Module |
|---------|---------|--------|
| RealtimeClient | PresenceClient, ApplicationLogsClient, etc. | @actschurch/ccms-sdk/realtime/* |
| useConnectionState() | usePresence().state | @actschurch/ccms-sdk/realtime/presence |
| usePresence() | usePresence() (new API) | @actschurch/ccms-sdk/realtime/presence |
| useRealtimeEvent() | useApplicationLogs(), useApiLogs(), etc. | @actschurch/ccms-sdk/realtime/logs |
For detailed migration instructions, see the Realtime Module Documentation.
License
MIT License - see LICENSE for details.
Support
- Documentation: docs.ccms.com
- Issues: GitHub Issues
- Email: [email protected]
