Skip to main content

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

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();