form_gear_engine_sdk 0.1.1 copy "form_gear_engine_sdk: ^0.1.1" to clipboard
form_gear_engine_sdk: ^0.1.1 copied to clipboard

Flutter SDK for FormGear - A flexible, JSON-driven form generation framework for dynamic data collection with 30+ input control types, nested forms, GPS, photo capture, and complex validation capabilities.

FormGear Logo

FormGear Flutter SDK #

A flexible, JSON-driven form generation framework for dynamic data collection

pub package License: MIT Flutter


A Flutter SDK for FormGear - A flexible, JSON-driven form generation framework for dynamic data collection, originally developed for BPS - Statistics Indonesia's FASIH App.

Features #

  • 🎯 JSON-driven forms with 30+ input control types
  • πŸ“± Multi-engine support: FormGear (ID 1) and FasihForm (ID 2)
  • πŸ“· Device integration: Camera, GPS, file uploads, signature capture
  • πŸ”’ Security: Input validation, HTTPS enforcement, log sanitization
  • πŸ’Ύ Offline capability: Forms work without internet
  • 🎨 Customizable listeners: SaveOrSubmit and FileUpload patterns

Installation #

dependencies:
  form_gear_engine_sdk: ^0.1.1

Platform Setup #

Android - Add to AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

iOS - Add to Info.plist:

<key>NSCameraUsageDescription</key>
<string>Camera access for form photos</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location access for GPS coordinates</string>

Quick Start #

1. Initialize SDK #

import 'package:form_gear_engine_sdk/form_gear_engine_sdk.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Configure API
  final apiConfig = FormGearApiConfig(
    baseUrl: 'https://your-api.com',
    formEngineEndpoint: '/api/form-engine/version',
    authToken: 'your-token',
  );

  // Initialize SDK
  final config = FormGearConfig(
    autoStartServer: true,
    serverPort: 8080,
    apiConfig: apiConfig,
    bpsUser: BpsUser(
      sessionToken: 'user-token',
      nipBaru: '123456789',
    ),
  );

  await FormGearSDK.instance.initialize(config);
  runApp(MyApp());
}

2. Open a Form with Assignment #

class FormPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () async {
        // Create assignment context
        final assignment = AssignmentContext(
          assignmentId: 'assignment_001',
          templateId: 'demo_template',
          surveyId: 'survey_2024',
          config: AssignmentConfig(
            lookupMode: FormGearLookupMode.offline,
            formMode: FormGearFormMode.open,
            clientMode: FormGearClientMode.capi,
          ),
          data: AssignmentData(
            template: {/* template data */},
            validation: {/* validation rules */},
            response: {/* form responses */},
          ),
        );

        // Open form with assignment
        await FormGearSDK.instance.openFormWithAssignment(
          context: context,
          assignment: assignment,
          title: 'Survey Form',
        );
      },
      child: Text('Open Form'),
    );
  }
}

3. Check Engine Version #

// Check if engine update is needed
final result = await FormGearSDK.instance.checkFormEngineVersion(
  context: context,
  engineId: '1',
);

if (result != null) {
  print('Current version: ${result.currentVersion}');
  print('Latest version: ${result.latestVersion}');
  print('Update available: ${result.updateAvailable}');
}

4. Check if Engine is Downloaded #

// Check if engine exists locally
final isDownloaded = await FormGearSDK.instance.isFormEngineDownloaded('1');

if (!isDownloaded) {
  // Show download screen or prompt
}

Public API Reference #

FormGearSDK #

Main SDK entry point.

Methods

Method Description
initialize(FormGearConfig config) Initialize SDK with configuration
openFormWithAssignment({BuildContext, AssignmentContext, ...}) Primary API - Open form with assignment context
checkFormEngineVersion({BuildContext? context, String? engineId}) Check for engine updates
isFormEngineDownloaded(String engineId) Check if engine exists locally
setFormDataListener(FormDataListener listener) Register save/submit listener
setFileUploadListener(FileUploadListener listener) Register file upload listener
removeFormDataListener() Remove save/submit listener
removeFileUploadListener() Remove file upload listener

Configuration Models #

FormGearConfig

FormGearConfig({
  bool autoStartServer = true,
  int serverPort = 8080,
  bool enableLogging = false,
  FormGearApiConfig? apiConfig,
  BpsUser? bpsUser,
  FormGearClientMode clientMode = FormGearClientMode.capi,
  FormGearLookupMode lookupMode = FormGearLookupMode.offline,
  FormGearFormMode formMode = FormGearFormMode.open,
})

FormGearApiConfig

FormGearApiConfig({
  String? baseUrl,
  String? formEngineEndpoint,
  String? authToken,
  Map<String, String> customHeaders = const {},
  bool isProduction = true,
  Map<String, List<String>>? pinnedCertificates, // For SSL pinning
})

BpsUser

BpsUser({
  String? sessionToken,
  String? authToken,
  String? nipBaru,
  String? nama,
  String? jabatan,
  String? org,
  // ... other fields
})

Enums #

FormGearClientMode

  • capi - Computer Assisted Personal Interviewing
  • cawi - Computer Assisted Web Interviewing

FormGearLookupMode

  • online - Fetch lookup data from server
  • offline - Use cached lookup data
  • local - Use local lookup data

FormGearFormMode

  • open - Form is editable
  • submitted - Form is read-only (submitted)
  • rejected - Form was rejected (editable)

SaveOrSubmit Listener #

Handle form save/submit operations with custom logic.

class MyFormDataListener extends FormDataListener {
  @override
  Future<SaveSubmitResult> onSaveOrSubmit(SaveSubmitData data) async {
    // Handle FormGear save/submit
    await myDatabase.save(data);
    return SaveSubmitResult.success(submissionId: 'form_${data.assignmentId}');
  }

  @override
  Future<SaveSubmitResult> onSaveOrSubmitFasihForm(SaveSubmitData data) async {
    // Handle FasihForm save/submit
    await myDatabase.saveFasih(data);
    return SaveSubmitResult.success(submissionId: 'fasih_${data.assignmentId}');
  }
}

// Register listener
FormGearSDK.instance.setFormDataListener(MyFormDataListener());

SaveSubmitData

class SaveSubmitData {
  final String assignmentId;
  final String templateId;
  final String surveyId;
  final Map<String, dynamic> formData;
  final Map<String, dynamic> remark;
  final List<dynamic> principal;
  final Map<String, dynamic>? reference; // FormGear only
  final Map<String, dynamic>? media;     // FormGear only
  final String flag; // 'save' or 'submit'
}

SaveSubmitResult

// Success
SaveSubmitResult.success(submissionId: 'abc123')

// Failure
SaveSubmitResult.failure(error: 'Database error')

FileUpload Listener #

Handle file uploads with custom backend integration.

class MyFileUploadListener implements FileUploadListener {
  @override
  Future<FileUploadResult> onFileUpload(FileUploadData data) async {
    // Upload to your backend (S3, server, etc.)
    final url = await uploadToBackend(data.file, data.fileName);
    return FileUploadResult.success(uploadedUrl: url);
  }

  @override
  void onUploadProgress(String fileName, int sent, int total) {
    print('Upload: ${(sent / total * 100).toInt()}%');
  }
}

// Register listener
FormGearSDK.instance.setFileUploadListener(MyFileUploadListener());

FileUploadData

class FileUploadData {
  final String assignmentId;
  final String templateId;
  final String dataKey;
  final File file;
  final String fileName;
  final String fileUri;
  final Map<String, dynamic>? metadata;
}

FileUploadResult

// Success
FileUploadResult.success(uploadedUrl: 'https://s3.amazonaws.com/...')

// Failure
FileUploadResult.failure(error: 'Upload failed')

Result Pattern #

Type-safe error handling for SDK operations.

final result = await checkFormEngineVersionUseCase();

result.fold(
  onFailure: (error) {
    print('Error: $error');
  },
  onSuccess: (response) {
    print('Version: ${response.version}');
  },
);

Result Types

sealed class Result<T> {}

class Success<T> extends Result<T> {
  final T data;
}

class Failure<T> extends Result<T> {
  final Object error;
  final StackTrace? stackTrace;
}

Models #

FormEngineEntity

class FormEngineEntity {
  final String id;            // '1' or '2'
  final String name;          // Engine name
  final String version;       // Version number
  final String? linkDownload; // Download URL
  final String? description;
}

VersionCheckResult

class VersionCheckResult {
  final FormEngineEntity engine;
  final String? currentVersion;
  final String? latestVersion;
  final bool updateAvailable;
  final VersionState state; // upToDate, updateAvailable, notInstalled
}

Security Features #

The SDK includes security best practices:

  • βœ… Path validation - Prevents path traversal attacks
  • βœ… HTTPS enforcement - Blocks insecure HTTP connections
  • βœ… Log sanitization - Redacts PII (NIK, phone, email, passwords)
  • βœ… SSL pinning - Certificate validation support
  • βœ… Required encryption keys - No hardcoded secrets

Example App #

See the example directory for a complete implementation showing:

  • SDK initialization
  • Form engine selection
  • Version checking
  • SaveOrSubmit listener implementation
  • FileUpload listener implementation

Run the example:

cd example
flutter pub get
flutter run

Migration from Previous Versions #

If you're upgrading from an older version, note these breaking changes:

Removed APIs #

The following internal APIs have been removed from the public surface:

  • FormGearDownloadManager - Use bundled assets or implement custom download
  • Template download methods - Manage templates in your app
  • Update screens - Implement custom UI for updates

Changed APIs #

  • FormGearApiConfig now only requires formEngineEndpoint (version check)
  • All form operations through FormGearSDK.instance methods
  • Listeners are now the recommended way to handle save/submit and uploads

Contributing #

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

License #

MIT License - see LICENSE file for details.

Support #


Made with ❀️ for FASIH App and the Flutter community

0
likes
140
points
58
downloads

Publisher

verified publisherbanuacoders.com

Weekly Downloads

Flutter SDK for FormGear - A flexible, JSON-driven form generation framework for dynamic data collection with 30+ input control types, nested forms, GPS, photo capture, and complex validation capabilities.

Homepage
Repository (GitHub)
View/report issues
Contributing

Documentation

API reference

License

MIT (license)

Dependencies

alice_dio, archive, camera, crypto, dio, encrypt, equatable, file_picker, flutter, flutter_bloc, flutter_inappwebview, flutter_svg, geolocator, get_it, image_picker, injectable, json_annotation, just_audio, mobile_scanner, mocktail, path, path_provider, percent_indicator, permission_handler, record, shelf, shelf_static, waveform_flutter

More

Packages that depend on form_gear_engine_sdk