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

Dbrij Ship for Flutter and Dart: feature flags, remote config, a kill switch and store version policy, resolved per device on one check in.

example/dbrij_ship_example.dart

// A complete, runnable use of Dbrij Ship in plain Dart:
//
//   dart run example/dbrij_ship_example.dart shp_your_app_key
//
// The same code works unchanged in a Flutter app. There, swap FileShipStorage for an
// adapter over shared_preferences (the README has the six lines) and read the
// version from package_info_plus instead of typing it.
import 'dart:convert';
import 'dart:io';

import 'package:dbrij_ship/dbrij_ship.dart';

/// Keeps the device id and the last answer in one small file.
///
/// Storage is not optional in a shipped app. Without it the device id is made again on
/// every launch, which turns one phone into thirty billable devices a month and
/// rerolls it in and out of every staged rollout.
class FileShipStorage implements ShipStorage {
  FileShipStorage(this.file);

  final File file;

  Future<Map<String, dynamic>> _read() async {
    if (!await file.exists()) return <String, dynamic>{};
    try {
      return jsonDecode(await file.readAsString()) as Map<String, dynamic>;
    } on FormatException {
      return <String, dynamic>{};
    }
  }

  @override
  Future<String?> getItem(String key) async => (await _read())[key] as String?;

  @override
  Future<void> setItem(String key, String value) async {
    final all = await _read();
    all[key] = value;
    await file.writeAsString(jsonEncode(all));
  }
}

Future<void> main(List<String> args) async {
  if (args.isEmpty) {
    stderr.writeln(
        'Pass your app key: dart run example/dbrij_ship_example.dart shp_...');
    exitCode = 64;
    return;
  }

  final ship = Ship(
    appKey: args
        .first, // from the Setup card on the Ship dashboard; public, not a secret
    channel: 'production',
    binaryVersion: '1.4.0',
    platform: Platform.isIOS ? 'ios' : 'android',
    storage: FileShipStorage(
        File('${Directory.systemTemp.path}/dbrij_ship_example.json')),
  );

  try {
    final answer = await ship.checkIn();

    // The kill switch: everything remote is off and your fallbacks are in charge.
    if (answer.killSwitch) {
      stdout.writeln('Kill switch is on: running on built in defaults.');
    }

    // The store version policy: the half of "update the app" that needs a store review.
    final binary = answer.binaryUpdate;
    if (binary != null) {
      stdout.writeln(binary.required
          ? 'This version is no longer supported. Update to ${binary.latestVersion}: ${binary.url ?? 'see the store'}'
          : 'Version ${binary.latestVersion} is available. ${binary.message}');
    }
  } on ShipException catch (e) {
    // Never let a release desk break the app it exists to protect: the reads below
    // still answer, from the last successful check in or from your fallbacks.
    stdout.writeln(
        'Could not check in (${e.message}); using what we already have.');
  }

  // Both read the last answer, which is cached, so they work offline. The fallback
  // is what shipped in your binary: it runs on first launch and under the kill switch.
  final newCheckout = ship.getFlag('new_checkout');
  final banner = ship.getConfig<String>('banner', '');
  stdout.writeln('new_checkout: $newCheckout');
  stdout.writeln('banner: ${banner.isEmpty ? '(none)' : banner}');

  ship.close();
}
0
likes
160
points
80
downloads

Documentation

Documentation
API reference

Publisher

verified publisherdbrij.com

Weekly Downloads

Dbrij Ship for Flutter and Dart: feature flags, remote config, a kill switch and store version policy, resolved per device on one check in.

Homepage

License

MIT (license)

Dependencies

archive, crypto, http

More

Packages that depend on dbrij_ship