Code Generation Reference
The fluttron generate services command generates type-safe Host/Client code from Dart service contracts.
Quick Start
# Generate from a service contract
fluttron generate services --contract lib/service_contract.dart
# Preview generated files without writing
fluttron generate services --contract lib/service_contract.dart --dry-run
# Generate into specific directories
fluttron generate services \
--contract lib/service_contract.dart \
--host-output my_service_host/lib/src/ \
--client-output my_service_client/lib/src/ \
--shared-output my_service_shared/lib/src/
Command Options
| Option | Description |
|---|---|
--contract, -c | Path to the service contract Dart file (required) |
--host-output | Output directory for host-side generated code |
--client-output | Output directory for client-side generated code |
--shared-output | Output directory for shared model generated code |
--dry-run | Preview generated files without writing to disk |
Contract Structure
A service contract is a Dart file containing:
- One or more abstract classes annotated with
@FluttronServiceContract - Zero or more model classes annotated with
@FluttronModel
import 'package:fluttron_shared/fluttron_shared.dart';
(namespace: 'weather')
abstract class WeatherService {
Future<WeatherInfo> getCurrentWeather(String city);
Future<List<WeatherForecast>> getForecast(String city, {int days = 5});
Future<bool> isAvailable();
}
()
class WeatherInfo {
final String city;
final double temperature;
final String condition;
final DateTime timestamp;
const WeatherInfo({
required this.city,
required this.temperature,
required this.condition,
required this.timestamp,
});
}
Generated Files
Host-Side Code
For each contract class, generates {class_name}_generated.dart:
// GENERATED CODE — DO NOT MODIFY BY HAND
// Generated by: fluttron generate services
// Source: service_contract.dart
import 'package:fluttron_host/fluttron_host.dart';
import 'package:fluttron_shared/fluttron_shared.dart';
abstract class WeatherServiceBase extends FluttronService {
String get namespace => 'weather';
Future<dynamic> handle(String method, Map<String, dynamic> params) async {
switch (method) {
case 'getCurrentWeather':
final city = _requireString(params, 'city');
final result = await getCurrentWeather(city);
return result.toMap();
case 'getForecast':
final city = _requireString(params, 'city');
final days = params['days'] == null ? 5 : params['days'] as int;
final result = await getForecast(city, days: days);
return result.map((e) => e.toMap()).toList();
case 'isAvailable':
return {'result': await isAvailable()};
default:
throw FluttronError(
'METHOD_NOT_FOUND',
'weather.$method not implemented',
);
}
}
Future<WeatherInfo> getCurrentWeather(String city);
Future<List<WeatherForecast>> getForecast(String city, {int days = 5});
Future<bool> isAvailable();
// Helper methods for parameter validation...
}
Usage: Extend the base class and implement the abstract methods:
import 'weather_service_generated.dart';
class WeatherServiceImpl extends WeatherServiceBase {
Future<WeatherInfo> getCurrentWeather(String city) async {
// Real implementation
return WeatherInfo(city: city, temperature: 22.5, ...);
}
Future<List<WeatherForecast>> getForecast(String city, {int days = 5}) async {
// Real implementation
}
Future<bool> isAvailable() async => true;
}
Client-Side Code
Generates {class_name}_client_generated.dart:
// GENERATED CODE — DO NOT MODIFY BY HAND
import 'package:fluttron_ui/fluttron_ui.dart';
class WeatherServiceClient {
WeatherServiceClient(this._client);
final FluttronClient _client;
Future<WeatherInfo> getCurrentWeather(String city) async {
final result = await _client.invoke(
'weather.getCurrentWeather',
{'city': city},
);
return WeatherInfo.fromMap(Map<String, dynamic>.from(result as Map));
}
Future<List<WeatherForecast>> getForecast(String city, {int days = 5}) async {
final result = await _client.invoke(
'weather.getForecast',
{'city': city, 'days': days},
);
return (result as List)
.map((e) => WeatherForecast.fromMap(
Map<String, dynamic>.from(e as Map)))
.toList();
}
Future<bool> isAvailable() async {
final result = await _client.invoke('weather.isAvailable', {});
return result['result'] as bool;
}
}
Model Code
For each @FluttronModel class, generates {model_name}_generated.dart:
// GENERATED CODE — DO NOT MODIFY BY HAND
class WeatherInfo {
final String city;
final double temperature;
final String condition;
final DateTime timestamp;
const WeatherInfo({
required this.city,
required this.temperature,
required this.condition,
required this.timestamp,
});
factory WeatherInfo.fromMap(Map<String, dynamic> map) {
return WeatherInfo(
city: map['city'] as String,
temperature: (map['temperature'] as num).toDouble(),
condition: map['condition'] as String,
timestamp: DateTime.parse(map['timestamp'] as String),
);
}
Map<String, dynamic> toMap() {
return {
'city': city,
'temperature': temperature,
'condition': condition,
'timestamp': timestamp.toIso8601String(),
};
}
}
Supported Types
Basic Types
| Dart Type | JSON Representation | Notes |
|---|---|---|
String | string | Direct mapping |
int | number | Direct mapping |
double | number | Uses (as num).toDouble() for safety |
bool | boolean | Direct mapping |
DateTime | string (ISO 8601) | Serialized via toIso8601String() |
Collection Types
| Dart Type | JSON Representation | Notes |
|---|---|---|
List<T> | array | Nested types supported |
Map<String, dynamic> | object | Direct mapping |
Nullable Types
All types support nullability with ? suffix:
String?→ null or stringList<int>?→ null or arrayDateTime?→ null or ISO 8601 string
Custom Model Types
Classes annotated with @FluttronModel are serialized via toMap() and deserialized via fromMap() factory.
Parameter Handling
Required Positional Parameters
Future<String> greet(String name);
Generated extraction:
final name = _requireString(params, 'name');
Throws FluttronError('BAD_PARAMS', ...) if missing or invalid.
Optional Named Parameters with Defaults
Future<String> greet({String name = 'World'});
Generated extraction:
final name = params['name'] == null ? 'World' : params['name'] as String;
Nullable Parameters
Future<void> update(String id, {String? value});
Generated extraction:
final id = _requireString(params, 'id');
final value = params['value'] == null ? null : params['value'] as String;
Regeneration Safety
- Generated files use
_generated.dartsuffix - Header includes timestamp for tracking
- Never modify generated files directly
- Extend the
*Baseclass for implementation
Error Handling
Generated code uses standard Fluttron errors:
| Error Code | Description |
|---|---|
METHOD_NOT_FOUND | Unknown method name |
BAD_PARAMS | Missing or invalid parameter |
Example:
throw FluttronError('BAD_PARAMS', 'Missing or invalid "city"');
Workflow
1. Define Contract
Create service_contract.dart with your service definition.
2. Generate Code
fluttron generate services --contract lib/service_contract.dart \
--host-output host/lib/src/ \
--client-output client/lib/src/ \
--shared-output shared/lib/src/
3. Implement Host
// host/lib/src/weather_service.dart
import 'weather_service_generated.dart';
class WeatherServiceImpl extends WeatherServiceBase {
Future<WeatherInfo> getCurrentWeather(String city) async {
// Your implementation
}
}
4. Register in Host App
// host/lib/main.dart
void main() {
final registry = ServiceRegistry()
..register(SystemService())
..register(StorageService())
..register(WeatherServiceImpl());
runFluttronHost(registry: registry);
}
5. Use in UI
// ui/lib/app.dart
import 'package:weather_service_client/weather_service_client.dart';
final client = FluttronClient();
final weatherService = WeatherServiceClient(client);
final weather = await weatherService.getCurrentWeather('London');
print('Temperature: ${weather.temperature}');
Limitations
- Nesting depth: Deeply nested generic types (e.g.,
Map<String, List<Map<String, int>>>) may fall back todynamic - No runtime discovery: Services must be manually registered
- JSON transport only: Binary protocols not supported
Next Steps
- Annotations Reference — Detailed annotation documentation
- Custom Services Tutorial — Step-by-step guide
- Services API — Built-in service clients