Overview
This guide covers essential best practices for integrating and using the FAD SDK effectively. Following these recommendations will help you build robust, maintainable, and user-friendly applications.
SDK Initialization
Single Instance Pattern
Always create a single SDK instance per process flow to avoid conflicts and resource issues.
async function processLiveness () {
const FAD_SDK = new FadSDK ( TOKEN , options );
try {
const response = await FAD_SDK . startFacetec ( CREDENTIALS , CONFIG );
return response ;
} finally {
FAD_SDK . end ();
}
}
Environment Configuration
Use appropriate environments based on your deployment stage:
// Development/Testing
const options = {
environment: FadSDK . getFadEnvironments (). UATHA ,
};
// Production
const options = {
environment: FadSDK . getFadEnvironments (). PRODUCTION ,
};
Store environment configuration in environment variables or configuration files, never hardcode production credentials in your source code.
Error Handling
Comprehensive Error Catching
Always implement comprehensive error handling with specific error code checks:
try {
const response = await FAD_SDK . startFacetec ( CREDENTIALS , CONFIGURATION );
// Process success
handleSuccess ( response );
} catch ( ex ) {
console . error ( 'SDK Error:' , ex );
// Handle specific error codes
switch ( ex . code ) {
case FadSDK . Errors . Facetec . Session . CAMERA_NOT_RUNNING :
showUserMessage ( 'Camera not available. Please check camera permissions.' );
break ;
case FadSDK . Errors . Facetec . Session . INITIALIZATION_NOT_COMPLETED :
showUserMessage ( 'Initialization failed. Retrying...' );
retryInitialization ();
break ;
case FadSDK . Errors . Facetec . Status . TIMEOUT :
showUserMessage ( 'Process timed out. Please try again.' );
break ;
case FadSDK . Errors . Facetec . Session . USER_CANCELLED :
showUserMessage ( 'Process cancelled by user.' );
break ;
default :
showUserMessage ( 'An unexpected error occurred. Please try again.' );
logErrorToService ( ex );
}
} finally {
FAD_SDK . end ();
}
Error Response Structure
Understand the error response structure:
interface ResponseError < T > {
code : T ; // Error code specific to the module
error : string ; // Human-readable error message
}
Different modules have different error codes. Always consult the module-specific documentation for complete error code lists.
User-Friendly Error Messages
if ( ex . code === FadSDK . Errors . Regula . CAMERA_PERMISSION_DENIED ) {
showNotification ({
title: 'Camera Access Required' ,
message: 'Please enable camera access in your browser settings to capture documents.' ,
type: 'warning' ,
actions: [{ label: 'Learn How' , onClick: showCameraHelp }]
});
}
Module Lifecycle Management
Always Use Finally Block
The end() method must always be called to cleanup resources:
const FAD_SDK = new FadSDK ( TOKEN , options );
try {
// Module operations
const response = await FAD_SDK . startRegula ( ... );
} catch ( ex ) {
// Error handling
handleError ( ex );
} finally {
// CRITICAL: Always cleanup
FAD_SDK . end ();
}
Failing to call FAD_SDK.end() can lead to memory leaks, camera/resource locks, and degraded performance.
Sequential Module Execution
When running multiple modules sequentially, ensure proper cleanup between them:
async function runMultipleModules () {
// First module: Document capture
let documentData ;
{
const FAD_SDK = new FadSDK ( TOKEN , options );
try {
documentData = await FAD_SDK . startRegula ( CREDENTIALS , TYPE , true , true , CONFIG );
} finally {
FAD_SDK . end ();
}
}
// Second module: Liveness check
let livenessData ;
{
const FAD_SDK = new FadSDK ( TOKEN , options );
try {
livenessData = await FAD_SDK . startFacetec ( CREDENTIALS , CONFIG );
} finally {
FAD_SDK . end ();
}
}
return { documentData , livenessData };
}
Handle Module Close Events
Always check if the user closed the module:
const response = await FAD_SDK . startRegula ( ... );
if ( response . event === FadSDK . Constants . EventModule . MODULE_CLOSED ) {
console . log ( 'User closed the module' );
// Don't treat this as an error - the user intentionally cancelled
return null ;
}
// Process normal response
processResponse ( response . data );
Resource Management
Camera Permissions
Request camera permissions before initializing camera-based modules:
async function checkCameraPermission () {
try {
const stream = await navigator . mediaDevices . getUserMedia ({ video: true });
// Permission granted, stop the stream
stream . getTracks (). forEach ( track => track . stop ());
return true ;
} catch ( err ) {
console . error ( 'Camera permission denied:' , err );
return false ;
}
}
async function startCapture () {
const hasPermission = await checkCameraPermission ();
if ( ! hasPermission ) {
showCameraPermissionHelp ();
return ;
}
// Proceed with SDK initialization
const FAD_SDK = new FadSDK ( TOKEN , options );
// ...
}
Memory Management for Large Files
Handle video and image data efficiently:
async function processSignature () {
const FAD_SDK = new FadSDK ( TOKEN , options );
try {
const response = await FAD_SDK . startSignature ( CONFIG );
// Create object URLs for display
const faceVideoUrl = URL . createObjectURL ( response . data . videoFace );
const signatureVideoUrl = URL . createObjectURL ( response . data . videoSignature );
// Use the URLs
displayVideos ( faceVideoUrl , signatureVideoUrl );
// Clean up object URLs when done to free memory
setTimeout (() => {
URL . revokeObjectURL ( faceVideoUrl );
URL . revokeObjectURL ( signatureVideoUrl );
}, 60000 ); // Revoke after 1 minute
} finally {
FAD_SDK . end ();
}
}
Use URL.revokeObjectURL() to free memory when object URLs are no longer needed.
Configuration Management
Separate Configuration Files
Store credentials and configuration separately from business logic:
// constants.ts - Configuration only
export const TOKEN = process . env . FAD_SDK_TOKEN || '' ;
export const CREDENTIALS = {
// Module-specific credentials
};
export const CONFIGURATION = {
// Module-specific configuration
};
Environment-Based Configuration
const getSDKOptions = () => {
const isDevelopment = process . env . NODE_ENV === 'development' ;
return {
environment: isDevelopment
? FadSDK . getFadEnvironments (). UATHA
: FadSDK . getFadEnvironments (). PRODUCTION ,
};
};
const FAD_SDK = new FadSDK ( TOKEN , getSDKOptions ());
User Experience
Loading States
Provide clear feedback during SDK operations:
async function captureDocument () {
const loadingOverlay = showLoading ( 'Initializing camera...' );
const FAD_SDK = new FadSDK ( TOKEN , options );
try {
loadingOverlay . updateMessage ( 'Capture your document...' );
const response = await FAD_SDK . startRegula ( CREDENTIALS , TYPE , true , true , CONFIG );
loadingOverlay . updateMessage ( 'Processing document...' );
await processDocument ( response . data );
loadingOverlay . hide ();
showSuccess ( 'Document captured successfully!' );
} catch ( ex ) {
loadingOverlay . hide ();
handleError ( ex );
} finally {
FAD_SDK . end ();
}
}
Retry Logic
Implement smart retry logic for transient errors:
async function startModuleWithRetry (
maxRetries = 3 ,
retryDelay = 1000
) : Promise < any > {
let lastError ;
for ( let attempt = 1 ; attempt <= maxRetries ; attempt ++ ) {
const FAD_SDK = new FadSDK ( TOKEN , options );
try {
const response = await FAD_SDK . startFacetec ( CREDENTIALS , CONFIG );
return response ;
} catch ( ex ) {
lastError = ex ;
// Don't retry user cancellations
if ( ex . code === FadSDK . Errors . Facetec . Session . USER_CANCELLED ) {
throw ex ;
}
// Don't retry permission errors
if ( ex . code === FadSDK . Errors . Facetec . Session . CAMERA_NOT_RUNNING ) {
throw ex ;
}
console . log ( `Attempt ${ attempt } failed, retrying...` );
await new Promise ( resolve => setTimeout ( resolve , retryDelay ));
} finally {
FAD_SDK . end ();
}
}
throw lastError ;
}
Progress Indicators
class SDKProcess {
private progressCallback : ( progress : number , message : string ) => void ;
constructor ( progressCallback ) {
this . progressCallback = progressCallback ;
}
async run () {
this . progressCallback ( 0 , 'Initializing...' );
const FAD_SDK = new FadSDK ( TOKEN , options );
try {
this . progressCallback ( 30 , 'Starting camera...' );
const response = await FAD_SDK . startFacetec ( CREDENTIALS , CONFIG );
this . progressCallback ( 70 , 'Processing results...' );
const processed = await this . processResponse ( response );
this . progressCallback ( 100 , 'Complete!' );
return processed ;
} finally {
FAD_SDK . end ();
}
}
}
Lazy Loading
Load the SDK only when needed:
let FadSDK ;
async function loadSDK () {
if ( ! FadSDK ) {
FadSDK = ( await import ( '@fad-producto/fad-sdk' )). default ;
}
return FadSDK ;
}
async function startProcess () {
const SDK = await loadSDK ();
const FAD_SDK = new SDK ( TOKEN , options );
// ...
}
Code Splitting
Split module implementations into separate chunks:
// liveness.ts
export async function runLivenessCheck () {
const FadSDK = ( await import ( '@fad-producto/fad-sdk' )). default ;
// Implementation
}
// document.ts
export async function captureDocument () {
const FadSDK = ( await import ( '@fad-producto/fad-sdk' )). default ;
// Implementation
}
// app.ts
import { runLivenessCheck } from './liveness' ;
import { captureDocument } from './document' ;
Security Best Practices
Token Management
Never expose authentication tokens in client-side code or version control systems.
// Good: Fetch token from your backend
async function getSDKToken () {
const response = await fetch ( '/api/sdk-token' , {
method: 'POST' ,
headers: { 'Authorization' : `Bearer ${ userAuthToken } ` }
});
const { token } = await response . json ();
return token ;
}
const token = await getSDKToken ();
const FAD_SDK = new FadSDK ( token , options );
Data Transmission
Securely transmit captured data to your backend:
async function submitCapturedData ( sdkResponse ) {
// Send data securely to your backend
const response = await fetch ( '/api/verify' , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'Authorization' : `Bearer ${ userAuthToken } `
},
body: JSON . stringify ({
data: sdkResponse . data ,
timestamp: Date . now (),
sessionId: getSessionId ()
})
});
return response . json ();
}
Testing
Mock SDK for Unit Tests
// __mocks__/@fad-producto/fad-sdk.ts
export default class MockFadSDK {
constructor ( token , options ) {}
async startFacetec ( credentials , config ) {
return {
data: {
auditTrail: [ 'mock-image-data' ],
lowQualityAuditTrail: [ 'mock-low-quality-data' ],
faceScan: 'mock-face-scan'
}
};
}
end () {}
static getFadEnvironments () {
return { UATHA: 'UATHA' , PRODUCTION: 'PRODUCTION' };
}
}
Integration Testing
describe ( 'FAD SDK Integration' , () => {
it ( 'should handle successful liveness check' , async () => {
const response = await runLivenessCheck ();
expect ( response . data ). toBeDefined ();
expect ( response . data . auditTrail ). toHaveLength ( 1 );
});
it ( 'should handle camera permission error' , async () => {
// Mock permission denial
await expect ( runLivenessCheck ()). rejects . toMatchObject ({
code: FadSDK . Errors . Facetec . Session . CAMERA_NOT_RUNNING
});
});
});
Logging and Monitoring
Structured Logging
const logger = {
sdkEvent ( event : string , data : any ) {
console . log ( '[FAD SDK]' , event , data );
// Send to your logging service
analyticsService . track ( 'sdk_event' , { event , ... data });
}
};
async function processModule () {
logger . sdkEvent ( 'module_start' , { module: 'liveness' });
const FAD_SDK = new FadSDK ( TOKEN , options );
try {
const response = await FAD_SDK . startFacetec ( CREDENTIALS , CONFIG );
logger . sdkEvent ( 'module_success' , { module: 'liveness' });
return response ;
} catch ( ex ) {
logger . sdkEvent ( 'module_error' , {
module: 'liveness' ,
error: ex . code ,
message: ex . error
});
throw ex ;
} finally {
FAD_SDK . end ();
logger . sdkEvent ( 'module_end' , { module: 'liveness' });
}
}
Next Steps
Troubleshooting Solutions to common issues
NPM Integration TypeScript/JavaScript integration
Vanilla JS Integration Script tag integration
API Reference Complete API documentation