PackageTrack
Sign in Get early access

bifrosted

The rainbow bridge connecting your app to APIs. A lightweight REST API client and repository pattern with caching, offline support, and error handling.

0.12.1 colbymaloy/bifrost

What this package is like to depend on

Last release 21 days ago

02 Aug 2026

Release timing varies

gaps range from 2 weeks to 5 months

Nearly every release is documented

notes for 15 of 16 stable releases

Nothing withdrawn

no release was ever pulled

6 months old

16 releases · first in 2026

16 releases in the last 12 months

see the full history below

Release timeline

16 releases · Feb 2026 to Aug 2026
Release Pre-release

Releases

latest 16
  1. 0.12.1 02 Aug 2026
    Release notes
    • Fixed the serialized cache-mutation queue retaining its completed Future across Flutter's per-test FakeAsync zones. A first widget test could cache successfully, while the next received its response and then waited forever on a completion owned by the previous test's inactive zone. The queue now clears its tail when the last mutation completes while preserving ordering for concurrent mutations.
    Open source →
  2. 0.12.0 02 Aug 2026
    Release notes
    • Breaking: replaced the shipped BifrostTestEnv service graph with BifrostTestRuntime. Test setup now resets only Bifrost's transport, preferences, clock, decoder, performance tracker, fake mode, notifications, and internal diagnostics. It never replaces bifrostServiceLocator; apps rebuild their own production container through initializeApplication.

      BifrostTestRuntime.install(
        responseFactory: (_) => const <Object>[],
        notifications: notifications,
        diagnostics: diagnostics,
        initializeApplication: AppBinding.reinitialize,
      );
      

      responseFactory, shouldFail, and responder now share the same per-request responder seam, so overrides reach HTTP clients retained by vendor SDKs such as Supabase. Notification tests record outcomes without replacing the app's real SystemNotifier registration.

    • Added non-recoverable FailureReason.internal. Unexpected defects thrown by source adapters, REST hooks, or repository callbacks no longer masquerade as network and get rescued by stale cache. fetch and mutate return an internal failure; the source-compatible boolean send returns false and records an internal diagnostic. Internal failures never invoke SystemNotifier.

    • RestAPI now bounds header resolution, each HTTP attempt, and unauthorized refresh. Override requestTimeout or refreshTimeout for API-specific budgets. Operational ClientException and timeout failures still return null; unexpected hook/client defects preserve their original error and stack in BifrostInternalException for repository containment. Timed-out refreshes remain single-flight until the underlying refresh actually ends.

    • Serialized the complete cache save, per-key clear, and clear-all mutations behind one failure-resilient queue shared by every repository instance. Two concurrent reads can no longer lose a registry entry and leave cached payloads that clearAllCache() cannot enumerate.

    • Added postgrestErrorResponse to package:bifrosted/testing.dart. It builds a complete PostgREST error envelope for tests that exercise a real retained Supabase/PostgREST client; production SQLSTATE/PGRST mapping remains app-owned.

    • Simplified Bifrost's private package test fixture: its locator is installed once per test file while its mutable services still reset before every test.

    Open source →
  3. 0.11.0 01 Aug 2026
    Release notes
    • Breaking: BifrostTestEnv.reset() no longer assigns bifrostServiceLocator. It was a second dependency-injection system running against the app's own. An app's bindings already point the locator at its container, so reset() and those bindings overwrote each other and which one won depended on call order — a repository test that ran reset() last silently stopped resolving the services its production code uses, while a widget test resolved them normally. Tests should exercise the same injection production does.

      Register the doubles through the app's own container instead:

      bifrostTestEnv.reset();
      Bind.delete<SystemNotifier>(force: true);   // GetX keeps the first permanent registration
      Bind.put<SystemNotifier>(bifrostTestEnv.notifier, permanent: true);
      

      A package with no container of its own — bifrosted included — can call bifrostTestEnv.installDoubles(), which does what reset() used to. It is documented as exactly that: a shim for the no-DI case, not something an app should reach for.

      Migration: if your tests broke with "…" not found after upgrading, add installDoubles() after reset() to restore the old behaviour, then move to container registration when convenient.

    Open source →
  4. 0.10.2 30 Jul 2026
    Release notes
    • Fixed: RestAPI.host rejected any value containing a colon. _buildUri passed host straight into Uri(scheme: 'https', host: host), and Uri's host parameter reads a colon as an IPv6 literal — so a scheme-qualified URL, a port, and therefore any local dev server threw FormatException: Illegal IPv6 address, invalid character (at character 1), an error naming none of the actual causes.

      host now accepts what you'd reasonably put in a config value:

      host Request URL
      api.example.com https://api.example.com/...
      https://api.example.com as given
      http://localhost:8080 as given — scheme and port preserved
      10.0.2.2:3000 https://10.0.2.2:3000/...
      https://example.com/v1 base path preserved, not dropped

      Backward compatible: a bare hostname still resolves to https.

    • An empty host now throws ArgumentError naming the likely cause — an app launched without --dart-define-from-file — instead of silently building https:///path and failing at the transport layer.

    Open source →
  5. 0.10.1 30 Jul 2026
    Release notes
    • Widened the logger re-export. Logger and Level alone were not enough to reconfigure bifrostLogger: its default DevelopmentFilter drops every log in release builds and ignores level, so keeping warnings in release meant naming ProductionFilter — which required adding a direct logger dependency just to reassign our own global. Now also exports ProductionFilter, DevelopmentFilter, LogFilter, LogPrinter, LogOutput, PrettyPrinter, and SimplePrinter.
      bifrostLogger = Logger(
        level: kReleaseMode ? Level.warning : Level.debug,
        filter: ProductionFilter(),   // required; DevelopmentFilter ignores `level`
      );
      
    Open source →
  6. 0.10.0 30 Jul 2026
    Release notes
    • Fixed: nothing persisted across app launches. SharedPrefService.init() called SharedPreferences.setMockInitialValues({}), which replaces the platform store with an empty in-memory map (SharedPreferencesStorePlatform.instance = InMemorySharedPreferencesStore.withData(...)). Because init() runs on every launch, no preference, token, onboarding flag, or cached response survived a cold start. init() now only reads. If your app appeared to "forget everything," this was why.
    • Breaking: removed SharedPrefService.updateInitialMock. It was test scaffolding on a production class, and it set the mock store as a side effect. Replace it with useMockStorage.
    • Added useMockStorage({values}) to package:bifrosted/testing.dart — the storage counterpart to useMockClient. Tests need it for two reasons: there is no SharedPreferences platform plugin in a test process, so getInstance() otherwise throws MissingPluginException; and the mock store is a static platform instance, so a value written by one test is still readable in the next unless it is reset. Call it in setUp (or once per file, before initServices):
      useMockStorage();                                   // clean slate
      useMockStorage(values: {'onboarding_done': true});  // seeded state
      
    • Added [OnboardingController], a reusable multi-step flow controller. Subclass it, implement buildResult, and inherit next/back/skip, answer collection, completion, and the analytics funnel.
    • It is a plain ChangeNotifier — no state-management dependency — matching the documented exception for one-time flows that run before the app's main state exists.
    • Emits the events a funnel is computed from: started, step_viewed, answered, skipped, back, completed (with duration, reach and skip count), and abandoned on dispose-before-completion, naming the step the user quit on. The event prefix is configurable.
    • step_viewed fires once per step per session, on first arrival only. Re-counting a revisit after back() would inflate early steps and overstate the funnel's health.
    • The controller reports events, not rates: a completion rate is a population statistic that one session cannot know. completed ÷ started is a query in your analytics tool.
    • back() never clears answers — losing input on a back tap is the most reliable way to cause abandonment.
    Open source →
  7. 0.5.4 15 Feb 2026
    Release notes
    • Breaking: Simplified [SystemNotifier] to three UI-only callbacks:
      • onNetworkError(), onUnauthorized(), onRequestFailed({statusCode, body})
      • Removed onForbidden, onServerError, onApiError
    • Docs: notifiers must handle user-facing UI only; use bifrostLogger for diagnostics
    Open source →
  8. 0.5.3 07 Feb 2026
    Release notes
    • Breaking: Removed fetchList — use fetch<List<T>> with the same fromJson
    • Breaking: Removed endpoint on fetch — use cacheKey only (it was only used for caching)
    • fetch<R, M> auto-detects top-level JSON array vs object; fromJson is always the item parser (User.fromJson), return type is User or List<User>
    Open source →
  9. 0.4.6 05 Feb 2026

    Nothing published for this version

  10. 0.4.5 05 Feb 2026
    Release notes
    • update dependencies
    Open source →
  11. 0.4.0 04 Feb 2026
    Release notes
    • Breaking: Removed generics from BifrostRepository
    • Added bifrostServiceLocator - Set once, used everywhere
      // At app startup:
      bifrostServiceLocator = <T>() => Get.find<T>();
      
    • Repositories now have zero boilerplate:
      class UserRepo extends BifrostRepository {
        Future<User?> getUser(String id) => fetch<User>(...);
      }
      
    Open source →
  12. 0.3.0 04 Feb 2026
    Release notes
    • Added global mock client support for testing
      • useMockClient() - Enable mock responses for all RestAPI instances
      • useRealClient() - Reset to real HTTP clients
      • setClientFactory() - Set custom client factory
      • No more per-API client overrides needed
    Open source →
  13. 0.2.2 04 Feb 2026
    Release notes
    • Fixed build.yaml to correctly combine generated code into .g.dart files
      • Changed build_to: cache and build_extensions: .fake.g.part
      • Generator output now properly merges with json_serializable/freezed
    Open source →
  14. 0.2.1 04 Feb 2026
    Release notes
    • Added build.yaml for auto-discovery by build_runner
      • No manual configuration needed - just add the dependency and run build_runner
      • Works like freezed/json_serializable out of the box
    Open source →
  15. 0.2.0 04 Feb 2026
    Release notes
    • Added @generateFake annotation for code generation
    • Added FakeUtils utility class (uses faker package)
      • fakeForKey(String key) - generates fake data based on field name
      • create<T>() - generates fake model from factory
      • fakeJson() / fakeJsonList() - generic JSON generators
    • Added FakeGenerator for build_runner integration
      • Generates .fake() extension methods for annotated classes
      • Works with freezed models
    Open source →
  16. 0.1.0 03 Feb 2026
    Release notes
    • Initial release
    • RestAPI abstract class for REST API clients
      • GET, POST, PUT, PATCH, DELETE methods
      • Automatic error handling and logging
      • Header management with extra headers support
    • BifrostRepository for repository pattern with caching
      • fetch<T>() and fetchList<T>() for automatic deserialization
      • Offline-first with cache fallback
      • Automatic cache expiration
    • SystemNotifier interface for global error handling
      • onNetworkError(), onUnauthorized(), onForbidden()
      • onServerError(), onApiError()
    • StorageService interface for pluggable storage backends
    • ConnectionChecker interface for connectivity detection
    • Uses logger package for logging
    • Comprehensive test suite
    Open source →

Every package, every release, already written down.

The archive is open and free. Watching your own project is what we are building next.

Browse the archive