Bridge Services Guide
Guide to using bridge services for communication between mini-app and host app.
Overview
Bridge services allow mini-apps to safely access host app features through serviceRouter.
┌─────────────┐ serviceRouter ┌─────────────┐
│ Mini-App │ ◄──────────────────► │ Host App │
│ │ invoke() │ Handlers │
└─────────────┘ └─────────────┘
Using in Mini-App
Via SDK (Recommended)
import {
storage,
analytics,
device,
network,
location,
media,
push,
haptics,
clipboard,
ui,
share,
} from '@54vie/miniapp-sdk';
// Storage
await storage.set('key', value);
const data = await storage.get('key');
// Analytics
analytics.track('event_name', { property: 'value' });
// Device info
const info = await device.getInfo();
// Network
const isOnline = await network.isOnline();
// Location
const position = await location.getCurrentPosition();
// Media
const photo = await media.takePhoto();
// Push
const token = await push.getToken();
// Haptics
haptics.notification('success');
// Clipboard
await clipboard.setString('copied text');
// UI
ui.showToast({ message: 'Success!', type: 'success' });
// Share
await share.text({ message: 'Check this out!' });
Direct serviceRouter (Advanced)
import { serviceRouter } from '@54vie/miniapp-sdk';
// Invoke a service
const result = await serviceRouter.invoke('storage', 'get', {
key: 'my-key',
scope: 'my-miniapp',
});
// With error handling
try {
const user = await serviceRouter.invoke('auth', 'getUser');
} catch (error) {
console.error('Failed to get user:', error);
}
Available Services
Storage Service
// Get value
const value = await serviceRouter.invoke('storage', 'get', { key: 'myKey' });
// Set value
await serviceRouter.invoke('storage', 'set', { key: 'myKey', value: data });
// Remove
await serviceRouter.invoke('storage', 'remove', { key: 'myKey' });
// Clear all
await serviceRouter.invoke('storage', 'clear', {});
Auth Service
// Get current user
const user = await serviceRouter.invoke('auth', 'getUser');
// Check authentication
const isAuth = await serviceRouter.invoke('auth', 'isAuthenticated');
// Get access token
const token = await serviceRouter.invoke('auth', 'getAccessToken');
// Request login (triggers host login flow)
await serviceRouter.invoke('auth', 'requestLogin', { returnTo: 'MyScreen' });
Analytics Service
// Track event
await serviceRouter.invoke('analytics', 'track', {
event: 'button_clicked',
properties: { button_name: 'checkout' },
});
// Track screen
await serviceRouter.invoke('analytics', 'screen', {
screenName: 'ProductDetail',
properties: { product_id: '123' },
});
Device Service
// Get all device info
const info = await serviceRouter.invoke('device', 'getInfo');
// Get device ID
const deviceId = await serviceRouter.invoke('device', 'getDeviceId');
// Check if emulator
const isEmulator = await serviceRouter.invoke('device', 'isEmulator');
Network Service
// Get network state
const state = await serviceRouter.invoke('network', 'getState');
// Check if online
const isOnline = await serviceRouter.invoke('network', 'isOnline');
// Check connection type
const type = await serviceRouter.invoke('network', 'getConnectionType');
Location Service
// Get current position
const position = await serviceRouter.invoke('location', 'getCurrentPosition', {
options: { accuracy: 'high' },
});
// Geocode address
const coords = await serviceRouter.invoke('location', 'geocode', {
address: '123 Nguyen Hue, Quan 1',
});
// Reverse geocode
const address = await serviceRouter.invoke('location', 'reverseGeocode', {
latitude: 10.7769,
longitude: 106.7009,
});
Media Service
// Take photo
const photo = await serviceRouter.invoke('media', 'takePhoto', {
options: { quality: 'high', cameraType: 'back' },
});
// Pick from gallery
const images = await serviceRouter.invoke('media', 'pickMultipleImages', {
options: { maxSelection: 5 },
});
// Crop image
const cropped = await serviceRouter.invoke('media', 'cropImage', {
uri: photo.uri,
options: { width: 300, height: 300 },
});
UI Service
// Show toast
await serviceRouter.invoke('ui', 'showToast', {
message: 'Saved!',
type: 'success',
});
// Show alert
const buttonIndex = await serviceRouter.invoke('ui', 'showAlert', {
title: 'Confirm',
message: 'Are you sure?',
buttons: [
{ text: 'Cancel', style: 'cancel' },
{ text: 'OK' },
],
});
// Show action sheet
await serviceRouter.invoke('ui', 'showActionSheet', {
title: 'Options',
options: [
{ label: 'Edit' },
{ label: 'Delete', destructive: true },
],
});
Haptics Service
// Impact
await serviceRouter.invoke('haptics', 'impact', { style: 'medium' });
// Notification
await serviceRouter.invoke('haptics', 'notification', { type: 'success' });
// Selection
await serviceRouter.invoke('haptics', 'selection');
Creating Custom Handlers (Host Side)
// In AppProviders.tsx
serviceRouter.register('myCustomService', {
doSomething: async (params, context) => {
const { appId } = context;
console.log(`Mini-app ${appId} called doSomething`);
return { success: true, data: 'result' };
},
anotherMethod: async ({ param1, param2 }) => {
// Process params
return { result: param1 + param2 };
},
});
Error Handling
try {
const result = await serviceRouter.invoke('service', 'method', params);
} catch (error) {
if (error.code === 'SERVICE_NOT_FOUND') {
console.error('Service not registered');
} else if (error.code === 'METHOD_NOT_FOUND') {
console.error('Method not found');
} else if (error.code === 'PERMISSION_DENIED') {
console.error('Permission not granted');
} else {
console.error('Unknown error:', error);
}
}
Best Practices
1. Use SDK over direct serviceRouter
// ✅ Recommended
import { storage } from '@54vie/miniapp-sdk';
await storage.set('key', value);
// ⚠️ Only when needed
import { serviceRouter } from '@54vie/miniapp-sdk';
await serviceRouter.invoke('storage', 'set', { key, value });
2. Handle errors gracefully
// ✅ Good
try {
const position = await location.getCurrentPosition();
} catch (error) {
// Fallback or show error
ui.showToast({ message: 'Cannot get location', type: 'error' });
}
3. Check permissions before using features
// ✅ Good
const hasPermission = await auth.checkPermission('camera');
if (!hasPermission) {
const granted = await auth.requestPermission('camera');
if (!granted) return;
}
const photo = await media.takePhoto();