flux_updater 1.0.0 copy "flux_updater: ^1.0.0" to clipboard
flux_updater: ^1.0.0 copied to clipboard

OTA update system for Flux applications with bytecode diff, version control, and seamless hot-reload capabilities.

example/main.dart

/// Flux OTA Example
///
/// This example demonstrates the complete OTA update workflow:
/// 1. Compiling Flux source to bytecode
/// 2. Creating releases with signing
/// 3. Uploading to OTA server
/// 4. Checking for updates
/// 5. Downloading and applying patches
///
/// Run with: dart run example/main.dart
library;

import 'package:flux_compiler/flux_compiler.dart';
import 'package:flux_updater/flux_updater.dart';
import 'package:shelf/shelf_io.dart' as shelf_io;

const signingKey = 'example-secret-key';
const appId = 'com.example.flux_ota_demo';

Future<void> main() async {
  print('╔═══════════════════════════════════════════════════════════╗');
  print('║           Flux OTA System - Complete Example              ║');
  print('╚═══════════════════════════════════════════════════════════╝\n');

  // Step 1: Start OTA Server
  print('📡 Starting OTA Server...');
  final server = FluxOtaServer(signingKey: signingKey);
  final httpServer = await shelf_io.serve(server.handler, 'localhost', 0);
  final serverUrl = 'http://localhost:${httpServer.port}';
  print('   Server running at: $serverUrl\n');

  // Step 2: Compile Version 1.0.0
  print('🔨 Compiling Version 1.0.0...');
  final v1Source = '''
    widget Counter {
      state count = 0;
      build {
        Column {
          Text("Count: " + toString(count))
          Button("Increment", onPressed: fn() {
            count = count + 1;
          })
        }
      }
    }
  ''';
  final v1Chunk = compileSource(v1Source);
  final v1Bytes = ChunkSerializer.serialize(v1Chunk);
  print('   Compiled: ${v1Bytes.length} bytes\n');

  // Step 3: Upload Version 1.0.0
  print('📤 Uploading Version 1.0.0...');
  final v1Release = FluxRelease(
    appId: appId,
    version: '1.0.0',
    buildNumber: 1,
    chunk: v1Bytes,
    signature: SignatureUtils.sign(v1Bytes, signingKey),
    createdAt: DateTime.now(),
  );
  server.registerRelease(v1Release);
  print('   Uploaded successfully!\n');

  // Step 4: Compile Version 1.1.0 (with a small change)
  print('🔨 Compiling Version 1.1.0...');
  final v2Source = '''
    widget Counter {
      state count = 0;
      build {
        Column {
          Text("Count: " + toString(count))
          Text("v1.1.0 - Now with double increment!")
          Button("Increment x2", onPressed: fn() {
            count = count + 2;
          })
        }
      }
    }
  ''';
  final v2Chunk = compileSource(v2Source);
  final v2Bytes = ChunkSerializer.serialize(v2Chunk);
  print('   Compiled: ${v2Bytes.length} bytes\n');

  // Step 5: Upload Version 1.1.0
  print('📤 Uploading Version 1.1.0...');
  final v2Release = FluxRelease(
    appId: appId,
    version: '1.1.0',
    buildNumber: 2,
    chunk: v2Bytes,
    signature: SignatureUtils.sign(v2Bytes, signingKey),
    createdAt: DateTime.now(),
  );
  server.registerRelease(v2Release);
  print('   Uploaded successfully!\n');

  // Step 6: Generate diff patch
  print('🔧 Generating diff patch...');
  final patch = await FluxDiffManager.createPatchFromBytes(v1Bytes, v2Bytes);
  final compressionRatio = (patch.length / v2Bytes.length * 100).toStringAsFixed(1);
  print('   Full chunk: ${v2Bytes.length} bytes');
  print('   Patch size: ${patch.length} bytes');
  print('   Compression: $compressionRatio%\n');

  // Step 7: Simulate client-side update check
  print('📱 Simulating client update check...');
  final versionManager = VersionManager();
  versionManager.registerRelease(v1Release);
  versionManager.registerRelease(v2Release);

  Chunk? receivedUpdate;
  final updateManager = FluxUpdateManager(
    appId: appId,
    serverUrl: serverUrl,
    signingKey: signingKey,
    currentBuildNumber: 1, // Currently on v1.0.0
    currentChunk: v1Chunk,
    versionManager: versionManager,
    onChunkReady: (chunk) {
      receivedUpdate = chunk;
      print('   ✅ Received updated chunk!');
    },
  );

  // Listen to progress
  updateManager.progressStream.listen((progress) {
    print('   Status: ${progress.status.name} - ${progress.message ?? ""}');
  });

  // Check for updates
  final status = await updateManager.checkForUpdates();
  print('   Update available: ${status == UpdateStatus.updateAvailable}\n');

  // Download and apply
  print('⬇️  Downloading and applying update...');
  final applyResult = await updateManager.downloadAndApply();
  print('   Result: ${applyResult.name}');
  print('   New build: ${updateManager.currentBuildNumber}\n');

  // Step 8: Verify update
  print('✅ Verification:');
  print('   Update received: ${receivedUpdate != null}');
  if (receivedUpdate != null) {
    print('   New chunk constants: ${receivedUpdate!.constants.length}');
  }

  // Step 9: Demonstrate rollback
  print('\n⏪ Demonstrating rollback to v1.0.0...');
  final rollbackSuccess = await updateManager.rollback('1.0.0');
  print('   Rollback success: $rollbackSuccess');
  print('   Current build: ${updateManager.currentBuildNumber}');

  // Cleanup
  updateManager.dispose();
  await httpServer.close();

  print('\n╔═══════════════════════════════════════════════════════════╗');
  print('║                    Example Complete!                       ║');
  print('╚═══════════════════════════════════════════════════════════╝');
}

Chunk compileSource(String source) {
  final lexer = Lexer(source);
  final tokens = lexer.tokenize();
  final parser = Parser(tokens);
  final unit = parser.parse();
  if (parser.errors.isNotEmpty) {
    throw Exception('Compilation failed: ${parser.errors}');
  }
  final compiler = Compiler(unit: unit);
  return compiler.endCompiler().chunk;
}
0
likes
140
points
106
downloads

Publisher

unverified uploader

Weekly Downloads

OTA update system for Flux applications with bytecode diff, version control, and seamless hot-reload capabilities.

Documentation

API reference

License

MIT (license)

Dependencies

archive, crypto, flux_compiler, http, path, shelf, shelf_router

More

Packages that depend on flux_updater