@oatfi/remote-loader
v1.2.4
Published
OatFi Remote Loader, a browser-only library for loading OatFi components from a remote source using JWT authentication
Readme
OatFi Remote Loader
A lightweight, TypeScript-first utility library for dynamically loading remote JavaScript components in web applications using OatFi platform authentication.
Features
- 🔐 Token-based Authentication - Secure loading using JWT tokens
- 🚀 Simple API - Load remote components with a single function call
- 🔒 Duplicate Prevention - Automatically prevents loading the same component multiple times
- ⚡ Promise-based - Modern async/await support
- 🎯 TypeScript Support - Full type definitions included
- 🛡️ Error Handling - Comprehensive error handling for authentication, API calls, and timeouts
- 🧪 Well Tested - Comprehensive test suite included
- 📦 Zero Dependencies - No external dependencies
- 🌐 Browser Only - Designed specifically for browser environments
Installation
npm install @oatfi/remote-loaderQuick Start
import { loadRemoteComponents } from '@oatfi/remote-loader';
// Load with authentication token
await loadRemoteComponents({
token: 'your-jwt-token-here',
});
// Load with custom configuration
await loadRemoteComponents({
token: 'your-jwt-token-here',
scriptId: 'my-component',
timeout: 5000,
env: 'prod',
});
// Load with fallback URL for local development
await loadRemoteComponents({
token: 'your-jwt-token-here',
fallbackRemoteComponentsUrl: 'http://localhost:3000/components.js',
});How It Works
The library works in three steps:
- Token Validation: Extracts the platform ID from your JWT authentication token
- Platform Lookup: Fetches platform details from the OatFi API using the extracted ID
- Component Loading: Dynamically loads the remote component from the URL provided in the platform response
Fallback Behavior: If platform details are unavailable or there are API errors, the library will use the fallbackRemoteComponentsUrl (if provided) to load components directly. This is particularly useful for local development when the platform API is not accessible.
API Reference
loadRemoteComponents(options)
Dynamically loads a remote JavaScript component by:
- Extracting platform ID from the provided JWT token
- Fetching platform details from the OatFi API
- Loading the remote component from the extracted URL
Parameters
options: Configuration object (required)token(string, required): JWT authentication token containing platform informationscriptId(string, optional): ID for the script element (default:'oatfi-remote-components')timeout(number, optional): Timeout in milliseconds (default:10000)env(string, optional): Environment for the API base URL (default:'qa')fallbackRemoteComponentsUrl(string, optional): Fallback URL for remote components when platform details are unavailable (useful for local development)
Returns
Promise<void>: Resolves when the component is loaded, rejects on error
Example
import { loadRemoteComponents } from '@oatfi/remote-loader';
try {
await loadRemoteComponents({
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
scriptId: 'external-widget',
timeout: 8000,
env: 'prod',
});
console.log('Component loaded successfully!');
} catch (error) {
console.error('Failed to load component:', error);
}removeRemoteComponent(scriptId?)
Removes a previously loaded remote component script from the DOM.
Parameters
scriptId(optional): ID of the script element to remove (default:'oatfi-remote-components')
Returns
boolean:trueif the script was found and removed,falseotherwise
Example
import { removeRemoteComponent } from '@oatfi/remote-loader';
// Remove the default script
if (removeRemoteComponent()) {
console.log('Component removed successfully');
}
// Remove a specific script
removeRemoteComponent('my-custom-component');isRemoteComponentLoaded(scriptId?)
Checks if a remote component script is already loaded in the DOM.
Parameters
scriptId(optional): ID of the script element to check (default:'oatfi-remote-components')
Returns
boolean:trueif the script is present,falseotherwise
Example
import { isRemoteComponentLoaded, loadRemoteComponents } from '@oatfi/remote-loader';
// Check before loading
if (!isRemoteComponentLoaded()) {
await loadRemoteComponents({ token: 'your-token' });
}
// Check for a specific component
if (isRemoteComponentLoaded('my-component')) {
console.log('My component is already loaded');
}Use Cases
Platform Integration
import { loadRemoteComponents } from '@oatfi/remote-loader';
// Load OatFi components for different platforms
const loadPlatformComponent = async (authToken: string) => {
await loadRemoteComponents({
token: authToken,
scriptId: 'oatfi-platform-component',
timeout: 15000,
});
};
// Use with your authentication system
const token = await getAuthToken();
await loadPlatformComponent(token);Multi-Environment Support
import { loadRemoteComponents } from '@oatfi/remote-loader';
const loadComponent = async (
token: string,
environment: 'local' | 'dev' | 'qa' | 'staging' | 'prod' = 'prod',
) => {
await loadRemoteComponents({
token,
env: environment,
scriptId: `oatfi-${environment}-component`,
});
};
// Load from different environments
await loadComponent('local-token', 'local');
await loadComponent('dev-token', 'dev');
await loadComponent('qa-token', 'qa');
await loadComponent('staging-token', 'staging');
await loadComponent('prod-token', 'prod');Local Development with Fallback URL
When developing locally or when platform details are not available, you can use the fallbackRemoteComponentsUrl parameter to load components from a specific URL:
import { loadRemoteComponents } from '@oatfi/remote-loader';
// For local development when platform API is not available
await loadRemoteComponents({
token: 'your-jwt-token', // Can be invalid for local dev
fallbackRemoteComponentsUrl: 'http://localhost:3000/components.js',
scriptId: 'local-dev-component',
});
// For development with a specific component version
await loadRemoteComponents({
token: 'your-jwt-token',
fallbackRemoteComponentsUrl: 'https://cdn.example.com/components/v1.2.3/bundle.js',
timeout: 10000,
});
// Fallback when platform details fail to load
await loadRemoteComponents({
token: 'your-jwt-token',
fallbackRemoteComponentsUrl: 'https://fallback.example.com/components.js',
env: 'prod',
});When to use fallbackRemoteComponentsUrl:
- Local Development: When the OatFi platform API is not accessible
- Offline Development: When working without internet connectivity
- Testing: When you need to test with specific component versions
- Platform Issues: When the platform API is temporarily unavailable
- Custom Components: When loading components from a custom CDN or server
The fallback URL will be used when:
- The JWT token is invalid or malformed
- The platform API returns an error (401, 404, 5xx)
- The platform response doesn't contain a
remote_components_url
Plugin System
import { loadRemoteComponents, isRemoteComponentLoaded } from '@oatfi/remote-loader';
class OatFiPluginManager {
async loadPlugin(authToken: string, pluginId: string) {
if (isRemoteComponentLoaded(pluginId)) {
console.log(`Plugin ${pluginId} is already loaded`);
return;
}
try {
await loadRemoteComponents({
token: authToken,
scriptId: pluginId,
timeout: 10000,
});
console.log(`Plugin ${pluginId} loaded successfully`);
} catch (error) {
console.error(`Failed to load plugin ${pluginId}:`, error);
}
}
}Error Handling
The library provides comprehensive error handling for various scenarios:
import { loadRemoteComponents } from '@oatfi/remote-loader';
try {
await loadRemoteComponents({
token: 'your-jwt-token',
timeout: 5000,
});
} catch (error) {
if (error.message.includes('Invalid token format')) {
console.error('The provided token is not a valid JWT');
} else if (error.message.includes('Token does not contain platform ID')) {
console.error('The token payload is missing platform information');
} else if (error.message.includes('Invalid or expired authentication token')) {
console.error('The token is invalid or has expired');
} else if (error.message.includes('Platform not found')) {
console.error('The platform ID from the token was not found');
} else if (error.message.includes('Platform response does not contain remote component URL')) {
console.error('The platform configuration is missing the component URL');
} else if (error.message.includes('timeout')) {
console.error('Component loading timed out');
} else if (error.message.includes('Failed to load remote components')) {
console.error('Network error or invalid component URL');
} else if (error.message.includes('browser environment')) {
console.error('Not running in a browser');
}
}Common Error Scenarios
- Invalid Token: Token format is incorrect or malformed
- Missing Platform ID: Token payload doesn't contain platform information
- Authentication Failed: Token is expired or invalid (401 response)
- Platform Not Found: Platform ID from token doesn't exist (404 response)
- Server Error: OatFi API server issues (5xx responses)
- Missing Component URL: Platform response doesn't include remote component URL
- Component Load Failure: Network issues or invalid component URL
- Timeout: Component loading exceeds the specified timeout
Token Requirements
Your JWT token must contain a platform identifier in one of these claim locations:
platformIdplatform_idsub(subject)aud(audience)
Instructions for Implementation
1. Get Your Authentication Token
First, you'll need to obtain a JWT token from your OatFi authentication system. This token should contain the platform ID in one of the supported claim locations.
2. Install the Library
npm install @oatfi/remote-loader3. Import and Use
import { loadRemoteComponents } from '@oatfi/remote-loader';
// Basic usage
try {
await loadRemoteComponents({
token: 'your-jwt-token-here',
});
console.log('Component loaded successfully!');
} catch (error) {
console.error('Failed to load component:', error);
}4. Handle Errors Appropriately
Implement proper error handling based on your application's needs:
try {
await loadRemoteComponents({ token: authToken });
} catch (error) {
if (error.message.includes('Invalid token format')) {
// Redirect to login or refresh token
await refreshAuthentication();
} else if (error.message.includes('Platform not found')) {
// Handle invalid platform
showPlatformError();
} else if (error.message.includes('timeout')) {
// Retry or show user-friendly message
showTimeoutMessage();
}
}5. Environment Configuration
For different environments, configure the appropriate environment:
const environment = process.env.NODE_ENV || 'qa';
const env = environment === 'prod' ? 'prod' : 'qa';
await loadRemoteComponents({
token: authToken,
env,
});Available Environments:
local- Local environmentdev- Development environmentqa- Quality Assurance environment (default)staging- Staging environmentprod- Production environment
6. Cleanup When Done
Remove components when they're no longer needed:
import { removeRemoteComponent } from '@oatfi/remote-loader';
// Remove specific component
removeRemoteComponent('my-component');
// Remove default component
removeRemoteComponent();7. Fix linting errors when consuming
When consuming the package in an external application, the linter might complain about the component or tag not being valid. To fix is include follow this:
React
Create custom-elements.d.ts:
import { Environment } from '@oatfi/remote-loader';
declare global {
namespace JSX {
interface IntrinsicElements {
'oatfi-account-opening': {
environment: Environment;
token: string;
};
}
}
}And include it in your tsconfig.json:
{
"compilerOptions": {
...
},
"include": ["custom-elements.d.ts", ...],
...
}Angular
Use CUSTOM_ELEMENTS_SCHEMA helper.
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
@Component({
selector: 'your-component',
...
schemas: [CUSTOM_ELEMENTS_SCHEMA],
...
})
export class YourComponent implements OnInit {
...Browser Compatibility
This library is designed specifically for browser environments and requires the following browser APIs:
- DOM APIs:
document,document.body,document.createElement - Base64 Decoding:
atob()function - Fetch API: For making HTTP requests to the OatFi API
- Promise Support: For async/await functionality
Supported Browsers:
- Chrome 63+ (ES2017+ support)
- Firefox 67+ (ES2017+ support)
- Safari 13+ (ES2017+ support)
- Edge 79+ (ES2017+ support)
Note: This library will not work in Node.js or other server-side environments.
Development
# Install dependencies
npm install
# Build the package
npm run build
# Run tests
npm test
# Build and watch for changes
npm run build:watchLicense
UNLICENSED
