mirror of
https://github.com/kuhyx/utils.git
synced 2026-11-13 23:50:58 +01:00
`crdt_sync` is pure Dart so it can run from CLI tools and headless systemd jobs, which means it takes closures instead of depending on flutter_secure_storage and google_sign_in. Every Flutter app then wrote the same ~390 lines to supply them, and five apps ended up carrying near-identical copies of firebase_backend.dart. Those copies drifted. `todo` gained an opt-out flag and a seeded-session path that home_inventory and wake_alarm never received, so the same bug was fixed in one copy and left live in the others -- which is the actual cost being paid here, not the line count. This package owns that glue once: the keystore adapter, the persisted per-install device id, the account store and a one-call bootstrap. A new app needs a SyncApp const and `openSync(kApp)`. The wrapper routes are a parameter rather than a constant, because todo's copy hardcoded its own `~/.config/todo/firebase_auth.json`. An extraction only one app could adopt would be worse than the copies. Also documents what made this hard to find: crdt_sync_dart's README covered only the *old* GitHub transport and never mentioned the Firebase surface at all, and sync_settings_ui -- a complete drop-in settings screen -- had no README whatsoever. The five existing apps stay on their copies and on crdt_sync_dart-v0.10.0. Migration is forward-only and those fallbacks are load-bearing; converging them is a separate task, and the README says so. 35 tests, 100% line coverage, no suppressions. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CFSGeWxHPY5rHUGrPqhcmG
40 lines
1.6 KiB
Dart
40 lines
1.6 KiB
Dart
/// The OS-keystore adapter every consuming app was writing by hand.
|
|
///
|
|
/// `crdt_sync` is pure Dart on purpose -- it runs from command-line tools and
|
|
/// headless systemd jobs -- so it cannot depend on `flutter_secure_storage`
|
|
/// and instead takes read/write/delete closures. Every Flutter app then wrote
|
|
/// the same three-line adapter, and four of them now differ only in which
|
|
/// bugs they have had fixed.
|
|
///
|
|
/// This file owns that adapter once.
|
|
library;
|
|
|
|
import 'package:crdt_sync/crdt_sync.dart';
|
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
|
|
/// Storage options shared with the GitHub token these apps already keep.
|
|
///
|
|
/// Off Android's deprecated `encryptedSharedPreferences` path, and libsecret
|
|
/// on Linux.
|
|
const FlutterSecureStorage kSecureStorage = FlutterSecureStorage();
|
|
|
|
/// Key the account blob (email + password) is stored under.
|
|
const String kAccountKey = kFirebaseAccountKey;
|
|
|
|
/// Key set when the user disconnects, to stop silent re-provisioning.
|
|
///
|
|
/// Without it the next launch re-adopts the account from whatever fallback is
|
|
/// available and the disconnect button looks broken.
|
|
const String kOptOutKey = kSyncAccountOptOutKey;
|
|
|
|
/// A [FirebaseCredentialStore] over the platform keystore.
|
|
///
|
|
/// Pass [storage] only in tests; production uses [kSecureStorage].
|
|
FirebaseCredentialStore keystoreCredentialStore({
|
|
FlutterSecureStorage storage = kSecureStorage,
|
|
}) => SecureCredentialStore(
|
|
read: (key) => storage.read(key: key),
|
|
write: (key, value) => storage.write(key: key, value: value),
|
|
delete: (key) => storage.delete(key: key),
|
|
);
|