Files
App/packages/miniapp-example/INTEGRATION.md

618 lines
14 KiB
Markdown

# Mini-App Example - Integration Overview
This document explains how the `miniapp-example` package integrates with the main Island application and the plugin registry system.
## Architecture Overview
```
Island Main App
├── PluginRegistry (lib/modular/registry.dart)
│ ├── loadMiniApp() # Downloads and caches .evc files
│ ├── enablePlugin() # Activates mini-app
│ └── launchMiniApp() # Runs mini-app in full-screen
├── PaymentAPI (lib/modular/api/payment.dart)
│ └── Singleton with internal Dio client
└── Eval Bridge
├── PaymentAPI instance registered
└── Available to mini-apps at runtime
```
## Integration Flow
### 1. Mini-App Development
```
Developer creates mini-app in packages/miniapp-example
Tests with `flutter test` (17 tests passing)
Runs with `flutter run` (debug mode)
Compiles with `dart run flutter_eval:compile -i lib/main.dart -o payment_demo.evc`
Uploads payment_demo.evc to server
```
### 2. Server Setup
Server provides mini-app metadata:
```json
{
"id": "payment-demo",
"name": "Payment Demo",
"version": "1.0.0",
"description": "Example payment mini-app",
"download_url": "https://your-server.com/mini-apps/payment_demo.evc",
"checksum": "sha256:abc123...",
"size": 3456,
"min_host_version": "1.0.0"
}
```
### 3. Main App Discovery
```dart
// In main app startup
final registry = ref.read(pluginRegistryProvider.notifier);
// Register PaymentAPI with eval bridge
registry.registerBridge('PaymentAPI', PaymentAPI.instance);
// Sync with server to discover mini-apps
await registry.syncMiniApps();
```
### 4. User Downloads Mini-App
```dart
// User selects mini-app from list
final miniApp = await registry.loadMiniApp(
'https://your-server.com/mini-apps/payment_demo.evc',
);
// PluginRegistry handles:
// 1. Download from server
// 2. Save to {appDocuments}/mini_apps/{id}/payment_demo.evc
// 3. Validate checksum
// 4. Cache locally
// 5. Save to SharedPreferences (enabled apps list)
```
### 5. Enable Mini-App
```dart
// User enables mini-app
await registry.enablePlugin('payment-demo');
// PluginRegistry:
// 1. Adds to enabled apps in SharedPreferences
// 2. Prepares for launch
```
### 6. Launch Mini-App
```dart
// User launches mini-app
await registry.launchMiniApp(context, 'payment-demo');
// PluginRegistry:
// 1. Loads .evc bytecode
// 2. Creates Runtime with flutter_eval
// 3. Provides PaymentAPI through eval bridge
// 4. Runs mini-app main() function
// 5. Displays full-screen
```
### 7. Mini-App Uses PaymentAPI
```dart
// Inside mini-app (payment_demo.evc)
// Access PaymentAPI through eval bridge
final paymentApi = PaymentAPI.instance;
// Create order
final order = await paymentApi.createOrder(
CreateOrderRequest(
amount: 19.99,
currency: 'USD',
description: 'Premium subscription',
),
);
// Process payment
final result = await paymentApi.processPaymentWithOverlay(
orderId: order.orderId,
);
// Show result
if (result.success) {
print('Payment successful!');
} else {
print('Payment failed: ${result.errorMessage}');
}
```
## Key Integration Points
### 1. PaymentAPI Registration
**Location**: `lib/modular/registry.dart`
```dart
class PluginRegistry {
final Map<String, dynamic> _bridge = {};
void registerBridge(String name, dynamic api) {
_bridge[name] = api;
}
// Called when loading mini-app
Runtime _createRuntime() {
return Runtime(
bridge: _bridge, // Pass PaymentAPI to mini-app
// ... other config
);
}
}
```
**Usage**: In main app startup
```dart
void main() async {
final registry = ref.read(pluginRegistryProvider.notifier);
// Register PaymentAPI
registry.registerBridge('PaymentAPI', PaymentAPI.instance);
runApp(MyApp());
}
```
### 2. Mini-App Loading
**Location**: `lib/modular/registry.dart` - `loadMiniApp()` method
```dart
Future<MiniApp> loadMiniApp(String url) async {
// 1. Download .evc file
final bytes = await _downloadFile(url);
// 2. Save to cache
final path = await _saveToCache(url, bytes);
// 3. Create MiniApp object
final miniApp = MiniApp(
id: _extractId(url),
bytecodePath: path,
// ... metadata
);
return miniApp;
}
```
### 3. Mini-App Launch
**Location**: `lib/modular/registry.dart` - `launchMiniApp()` method
```dart
Future<void> launchMiniApp(BuildContext context, String id) async {
// 1. Get mini-app
final miniApp = _getMiniApp(id);
// 2. Load bytecode
final bytecode = await File(miniApp.bytecodePath).readAsBytes();
// 3. Create runtime with PaymentAPI bridge
final runtime = _createRuntime();
// 4. Execute mini-app
final program = runtime.loadProgram(bytecode);
program.execute();
// 5. Navigate to mini-app screen
Navigator.push(
context,
MaterialPageRoute(builder: (_) => MiniAppScreen(program)),
);
}
```
## Data Flow
### Mini-App Request Flow
```
Mini-App (payment_demo.evc)
PaymentAPI instance (from eval bridge)
PaymentAPI class (lib/modular/api/payment.dart)
Dio client (internal)
Server API (your payment server)
Response back to mini-app
```
### State Management
```
SharedPreferences (Persistent)
├── enabled_mini_apps: ['payment-demo', ...]
└── last_sync: '2025-01-18T00:00:00Z'
File System (Cached .evc files)
└── {appDocuments}/mini_apps/
├── payment-demo/
│ └── payment_demo.evc
└── other-miniapp/
└── app.evc
Runtime (Memory)
├── Loaded mini-apps
└── Bridge APIs (PaymentAPI, etc.)
```
## File Locations
### Main App Files
```
lib/
├── modular/
│ ├── interface.dart # Plugin interfaces
│ ├── registry.dart # PluginRegistry class
│ ├── api/
│ │ └── payment.dart # PaymentAPI implementation
│ └── README.md # Plugin system docs
└── pods/
└── plugin_registry.dart # Riverpod providers
```
### Mini-App Example Files
```
packages/miniapp-example/
├── lib/
│ ├── main.dart # Mini-app code
│ └── payment_api.dart # API reference
├── test/
│ └── main_test.dart # Widget tests
├── README.md # API usage docs
├── BUILD_GUIDE.md # Build instructions
├── SUMMARY.md # This document
├── build.sh # Build script
└── pubspec.yaml # Package config
```
### Generated Files
```
build/ # Build artifacts (ignored)
*.evc # Compiled bytecode (optional)
*.freezed.dart # Generated code
*.g.dart # Generated code
```
## Configuration
### Main App Setup
1. **Add to pubspec.yaml**:
```yaml
dependencies:
flutter_eval: ^0.8.2
```
2. **Initialize PluginRegistry**:
```dart
final registry = ref.read(pluginRegistryProvider.notifier);
await registry.initialize();
registry.registerBridge('PaymentAPI', PaymentAPI.instance);
```
3. **Set up server**:
```dart
final serverInfo = MiniAppServerInfo(
baseUrl: 'https://your-server.com/api',
miniAppsPath: '/mini-apps',
);
registry.setServerInfo(serverInfo);
```
### Mini-App Setup
1. **Create package**:
```bash
mkdir packages/my-miniapp
cd packages/my-miniapp
flutter create --org com.example my_miniapp
```
2. **Add flutter_eval**:
```yaml
dependencies:
flutter_eval: ^0.8.2
```
3. **Write mini-app**:
```dart
import 'package:flutter/material.dart';
class MyMiniApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(child: Text('Hello from Mini-App!')),
),
);
}
}
void main() => runApp(MyMiniApp());
```
4. **Test and build**:
```bash
flutter test
dart run flutter_eval:compile -i lib/main.dart -o my_miniapp.evc
```
## Testing Strategy
### Unit Tests
Test business logic in isolation:
```dart
test('PaymentAPI should create order', () async {
final api = PaymentAPI.instance;
final order = await api.createOrder(
CreateOrderRequest(
amount: 19.99,
currency: 'USD',
description: 'Test',
),
);
expect(order.orderId, isNotEmpty);
});
```
### Widget Tests
Test UI components:
```bash
cd packages/miniapp-example
flutter test
```
### Integration Tests
Test full flow:
```dart
testWidgets('mini-app should process payment', (tester) async {
// Setup registry
final registry = PluginRegistry();
registry.registerBridge('PaymentAPI', PaymentAPI.instance);
// Load mini-app
final miniApp = await registry.loadMiniApp('test.evc');
// Launch
await registry.launchMiniApp(tester.element(miniApp), miniApp.id);
// Test payment flow
await tester.tap(find.text('Pay with Overlay'));
await tester.pumpAndSettle();
expect(find.text('Payment successful!'), findsOneWidget);
});
```
## Troubleshooting
### Mini-App Won't Load
**Checklist**:
- [ ] .evc file exists at expected path
- [ ] File is not corrupted (verify checksum)
- [ ] PaymentAPI is registered with bridge
- [ ] flutter_eval is properly initialized
- [ ] Mini-app main() function exists
**Debug**:
```dart
// Add logging in registry.dart
print('Loading mini-app from: $path');
print('Bytecode size: ${bytecode.length}');
print('Bridge APIs: ${_bridge.keys}');
```
### PaymentAPI Not Available
**Checklist**:
- [ ] PaymentAPI is registered before mini-app loads
- [ ] Bridge name matches ('PaymentAPI')
- [ ] Singleton instance is not null
- [ ] Dio client is configured
**Debug**:
```dart
// Check bridge
print('Bridge has PaymentAPI: ${_bridge.containsKey('PaymentAPI')}');
// Check instance
print('PaymentAPI.instance: ${PaymentAPI.instance}');
```
### Network Errors
**Checklist**:
- [ ] Server URL is accessible
- [ ] API endpoints are correct
- [ ] Authentication token exists
- [ ] Network permissions granted
**Debug**:
```dart
// Add Dio interceptors for logging
dio.interceptors.add(LogInterceptor(
request: true,
response: true,
error: true,
));
```
## Best Practices
### For Mini-App Developers
1. **Keep it Small**: Mini-apps should be focused and lightweight
2. **Test Thoroughly**: Write comprehensive tests for all user flows
3. **Handle Errors**: Always wrap API calls in try-catch
4. **Show Feedback**: Provide loading states and user feedback
5. **Use Official APIs**: Only use PaymentAPI and other provided APIs
6. **Version Control**: Include version information in metadata
7. **Security**: Never store sensitive data or API keys
### For Main App Developers
1. **Register APIs Early**: Register all bridge APIs before loading mini-apps
2. **Handle Failures**: Gracefully handle mini-app load failures
3. **Cache Wisely**: Implement proper caching for .evc files
4. **Validate Metadata**: Verify server metadata before loading
5. **Secure Bridge**: Only expose necessary APIs to mini-apps
6. **Monitor Usage**: Track mini-app usage and performance
7. **Update System**: Keep flutter_eval and dependencies updated
## Performance Considerations
### Load Time Optimization
1. **Compress .evc files**: Use gzip compression for download
2. **Lazy Loading**: Only load bytecode when needed
3. **Prefetch**: Download popular mini-apps in background
4. **Cache Validation**: Use ETags for cache validation
### Memory Optimization
1. **Unload When Done**: Release mini-app resources when closed
2. **Limit Concurrent Apps**: Only load one mini-app at a time
3. **Clean Up Runtime**: Dispose runtime after mini-app exits
4. **Monitor Memory**: Track memory usage during operation
### Network Optimization
1. **Batch Requests**: Combine multiple requests when possible
2. **Retry Logic**: Implement exponential backoff for retries
3. **Offline Support**: Cache responses for offline use
4. **Compression**: Enable compression for API responses
## Security Considerations
### Mini-App Sandbox
Mini-apps run in a sandboxed environment:
- Limited file system access
- No direct network access (through bridge APIs only)
- No access to other mini-apps
- Limited device permissions
### PaymentAPI Security
- Internal Dio client (no external dependencies)
- Token management via SharedPreferences
- HTTPS-only connections
- Automatic error logging
- No sensitive data in logs
### Best Practices
1. **Validate Inputs**: Always validate user inputs
2. **Encrypt Data**: Encrypt sensitive data at rest
3. **Use HTTPS**: Always use HTTPS for API calls
4. **Minimize Permissions**: Request minimum necessary permissions
5. **Regular Updates**: Keep dependencies updated
6. **Audit Logs**: Review audit logs regularly
## Future Enhancements
### Planned Features
1. **Hot Reload**: Support live reloading during development
2. **Plugin System**: Allow mini-apps to use plugins
3. **Version Management**: Automatic version checking and updates
4. **Analytics**: Built-in analytics for mini-app usage
5. **Marketplace**: Mini-app marketplace UI
6. **Permissions System**: Fine-grained permissions for mini-apps
### Potential Improvements
1. **Smaller Bytecode**: Reduce .evc file size
2. **Faster Compilation**: Improve compilation speed
3. **Better Debugging**: Enhanced debugging tools
4. **Offline Support**: Better offline functionality
5. **Background Tasks**: Support for background operations
## Resources
### Documentation
- **Plugin System**: `lib/modular/README.md`
- **Payment API**: `lib/modular/api/README.md`
- **Build Guide**: `packages/miniapp-example/BUILD_GUIDE.md`
- **API Reference**: `packages/miniapp-example/lib/payment_api.dart`
### Code Examples
- **Mini-App Example**: `packages/miniapp-example/lib/main.dart`
- **Widget Tests**: `packages/miniapp-example/test/main_test.dart`
- **Plugin Registry**: `lib/modular/registry.dart`
- **Payment API**: `lib/modular/api/payment.dart`
### Tools
- **Build Script**: `packages/miniapp-example/build.sh`
- **Flutter Eval**: https://pub.dev/packages/flutter_eval
- **Flutter Docs**: https://flutter.dev/docs
## Support
For issues or questions:
1. Check documentation files
2. Review code examples
3. Check test cases
4. Review PaymentAPI interface
5. Consult build guide
## Conclusion
The mini-app example demonstrates a complete integration between:
- Main app with PluginRegistry
- PaymentAPI with internal Dio client
- Mini-app compiled to .evc bytecode
- Eval bridge providing API access
This architecture enables:
- Dynamic loading of mini-apps
- Secure API access through bridge
- Full-screen mini-app experience
- Version management and updates
- Caching and offline support
For more details, see the documentation files listed above.