baaba_storage_utils
A unified Flutter storage package combining SharedPreferences, Hive, and Flutter Secure Storage with a clean, simple API.
1.3.0
What this package is like to depend on
Last release 4 days ago
20 Aug 2026
Too new to tell
only 2 release windows
Most releases are documented
notes for 4 of 5 stable releases
Nothing withdrawn
no release was ever pulled
3 months old
5 releases · first in 2026
5 releases in the last 12 months
see the full history below
Release timeline
5 releases · May 2026 to Aug 2026Releases
latest 5-
1.3.020 Aug 2026Release notes
Open source →Added — encryption at rest for Hive boxes
A Hive box was previously always a cleartext file in the app's data directory, and the wrapper offered no way to change that:
Hive.openBoxaccepts anencryptionCipher, but none ofopenBox,openTypedBoxoropenLazyBoxpassed one through. An app storing PII on-device had no route to an encrypted box except bypassing this package.All three openers now take an optional cipher:
await BaabaStorage.hive.openBox( 'citizens', encryptionCipher: await BaabaStorage.hiveCipher(), );API Purpose hive.openBox(name, {encryptionCipher, crashRecovery})Open a regular box, optionally AES-256 encrypted hive.openTypedBox<E>(name, {encryptionCipher, crashRecovery})Same, for a box of custom objects hive.openLazyBox(name, {encryptionCipher, crashRecovery})Same, for a lazy box BaabaStorage.hiveCipher({key})Resolves a stable per-install AES-256 key out of Keystore-backed secure storage, generating one from a CSPRNG on first use. Memoised and single-flight, so concurrent opens cannot race into generating two keys BaabaStorage.hiveKeyAliasThe secure-storage key hiveCipheruses, so consumers need not hardcode ithive.boxExistsOnDisk(name)Whether a file exists for a box, without opening it — the only way to tell "first run" from "the box is here but its key is gone", which need opposite handling BoxEncryptionMismatchExceptionThrown when a box is already open with a different encryption intent than the one requested The package now also re-exports
HiveCipherandHiveAesCipher, so a consumer can name those types without addinghiveto its own pubspec.Fixed — the already-open box silently ignored the cipher
Hive documents that on an already-open box "all provided parameters are being ignored", and that includes
encryptionCipher. Every opener here short-circuits on an open box, so this returned a plaintext box with no error and no encryption:await BaabaStorage.hive.openBox('citizens'); // cleartext await BaabaStorage.hive.openBox( // same box! 'citizens', encryptionCipher: await BaabaStorage.hiveCipher(), );HiveStoragenow records the encryption intent of every box it opens and throwsBoxEncryptionMismatchExceptionwhen a later open disagrees, in either direction. A box adopted from a bareHive.openBoxelsewhere in the app counts as unknown rather than unencrypted: requesting it plaintext behaves exactly as before, requesting it encrypted throws, because an unverifiable claim of encryption is not one this package will make.Changed —
crashRecoverydefaults tofalseon an encrypted openOnly affects the new ciphered code path; a call without a cipher is unchanged.
Hive computes each frame's checksum over the encryption key, so opening a cleartext box with a cipher — or an encrypted box with the wrong key — fails the checksum on the first frame. Hive's
crashRecoverydefault oftruereads that as a corrupt file, truncates it, and returns an empty box without throwing. For a damaged cleartext cache that is a reasonable trade. For an encrypted box, where a key that does not match is far more likely than a damaged file, it turns a recoverable problem into silent, permanent data loss.A ciphered open therefore defaults to
crashRecovery: false, which raises aHiveErrorand leaves the file untouched. Pass the flag explicitly to get Hive's behaviour back.Note this protection cannot extend across sessions: nothing in a
.hivefile records whether it is encrypted, so opening an encrypted box without its cipher still looks like corruption to Hive and still truncates. Resolve the cipher once at startup and pass it to every open of that box.Notes for adopting encryption on existing data
Two things a consumer must handle, both documented in the README:
- A cleartext box cannot be reopened with a cipher. Adding the parameter to a box that already holds data does not migrate it. Migration — read plaintext, write to a new encrypted box, then delete the original — belongs in the app, and the order matters.
android:allowBackupmust befalse. The.hivefiles travel in an Android Auto Backup; the Keystore-backed key does not. A restore onto a new device would produce encrypted boxes with no key to decrypt them.
Backward compatible: every new parameter is optional and named, and no existing call site changes behaviour.
-
1.2.013 Aug 2026Release notes
Open source →Fixed — lazy and typed boxes were unusable through the wrapper
Every data operation resolved its box with
Hive.box(name), which only accepts an eagerly-opened box whose value type is exactlydynamic.Hive.isBoxOpen, however, answerstruefor every flavour — so theBoxNotOpenExceptionguard passed and Hive then threwHiveError: The box "x" is already open and of type LazyBox<dynamic>, an error naming neither this package nor the caller's mistake.In practice that meant choosing
openLazyBoxoropenTypedBox<T>disabled the entire wrapper:put,putAll,get,delete,deleteKeys,clearBox,getAll,getKeys,containsKey,length,isEmpty,watch,listenableandcloseBoxall threw.closeBoxwas the one most likely to bite first, in a "log out and clear storage" path.HiveStoragenow tracks the boxes it opens, along with the value type each was opened with, and routes every operation to the widest Hive type that supports it. Operations declared onBoxBase— all writes, deletes, and metadata, pluswatchandcloseBox— now work on lazy and typed boxes alike.Boxes opened outside
BaabaStorage(a bareHive.openLazyBoxelsewhere in your app) are adopted on first use, so the wrapper works on them too.Backward compatible: the change only affects paths that previously threw.
Added
API Purpose hive.getLazy<E>(box, key, {defaultValue})Async read; works on lazy and regular boxes hive.getAllLazy<E>(box)Async read of every value; works on both flavours hive.isBoxLazy(box)trueif the box is open and was opened lazilyBoxIsLazyExceptionThrown by get/getAll/listenableon a lazy box, naming the operation and pointing at the async equivalentBoxTypeMismatchExceptionThrown when a box name is already open in another flavour, replacing a raw HiveErrorThe package now re-exports the Hive types its own API returns —
Box,LazyBox,BoxBase,BoxEvent,TypeAdapter,BinaryReader,BinaryWriter,HiveError,HiveObject,HiveObjectMixin— so consuming apps can write those types in their own signatures without addinghiveto their pubspec. (Adapters generated byhive_generatorare the exception: the generated code emits its ownhiveimport.)hiveis now a direct dependency so the re-exported version is one this package pins.Changed
putAllis nowputAll<E>(String boxName, Map<dynamic, E> entries). Hive checks the map against the box's value type as a whole, so aMap<dynamic, dynamic>could never satisfy aBox<UserProfile>even when every value was one. Inference makes this source-compatible.deleteBoxnow calls the initialisation guard, so using it beforeBaabaStorage.init()raisesStorageNotInitializedExceptioninstead of failing inside Hive.- README: the custom-objects example called
openBox<UserProfile>, which does not exist — it isopenTypedBox<UserProfile>.
-
1.1.105 May 2026Nothing published for this version
-
1.1.005 May 2026Release notes
Open source →Added — Reactive SharedPreferences
PrefsStoragenow emits change events so UI widgets can rebuild automatically without manualsetStatecalls, matching the reactive API already available onHiveStorage.API Returns Use with prefs.watch<T>('key')Stream<T?>StreamBuilderprefs.listenable('key')ValueListenable<dynamic>ValueListenableBuilderprefs.changesStream<MapEntry<String, dynamic>>general listener All write methods (
setString,setInt,setDouble,setBool,setStringList,set<T>,remove,clear) now dispatch a change event after a successful write.removeandclearemitnullas the value.
-
1.0.005 May 2026Release notes
Open source →Initial release.
BaabaStorage— unified facade that initialises all three backends with a singleawait BaabaStorage.init()call.PrefsStorage— singleton wrapper aroundshared_preferenceswith typed getters/setters (getString,setInt, …) and a genericget<T>/set<T>API. SupportsString,int,double,bool, andList<String>.HiveStorage— singleton wrapper aroundhive_flutterwith box management (openBox,openTypedBox,openLazyBox), bulk operations (putAll,getAll,deleteKeys), TypeAdapter registration, and reactive helpers (watch,listenable).SecureStorage— singleton wrapper aroundflutter_secure_storagewith auth-token shortcuts (saveToken,getToken,hasToken,deleteToken), HTTP-header storage (saveAuthHeaders,getAuthHeaders,deleteAuthHeaders), and configurable platform options.- Exceptions —
StorageNotInitializedException,BoxNotOpenException,UnsupportedTypeExceptionwith descriptive messages.