bloom_framework 0.4.1
bloom_framework: ^0.4.1 copied to clipboard
An opinionated application framework and developer platform built on Dart and Flutter.
Changelog #
0.4.1 #
Fixed #
bloom_frameworkcould not be resolved by any consumer outside this repository. Its hosted constraints onbloom_seo(^0.1.1) andbloom_js_native(^0.2.0) contradicted what its own siblings require —bloom_server ^0.2.0depends onbloom_seo ^0.2.0, and bothbloom_seoandbloom_serverdepend onbloom_js_native ^0.3.0— sopub getfailed with "version solving failed" on 0.3.1 and 0.4.0. The constraints are now^0.2.0and^0.3.0, matching the versions the monorepo'sdependency_overridesalready resolve to, so the published package resolves to exactly what is built and tested here. The overrides had masked the contradiction locally.
0.4.0 #
Bloom Framework no longer depends on Flutter's Material library. Every widget it ships is
now built on package:flutter/widgets.dart and the Bloom UI primitives.
Breaking #
BloomApp.themeandBloomApp.darkThemeare nowBloomThemerather thanThemeData, andBloomApp.themeModeisBloomThemeModerather thanThemeMode. PassBloomTheme.light/BloomTheme.dark(or your ownBloomTheme) instead of aThemeData. There is no Material-free equivalent ofThemeData, so this change is unavoidable rather than stylistic.pumpBloomApp'stheme:parameter follows the same change, fromThemeData?toBloomTheme?.
Added #
bloom_uiis now a dependency. The framework's widgets — the app shell, the 404 page, the OTA update banner and dialog, the dev inspector overlay and the native view fallback — are built from Bloom UI primitives rather than Material ones.
Changed #
BloomAppnow wrapsBloomApp.routerfrombloom_uiinstead ofMaterialApp.router. Note thatbloom_uialso exports aBloomApp; framework sources importbloom_uiunder auiprefix, and the framework does not re-export it, so consumers see no ambiguity.BloomMobileApp's dark theme is expressed as aBloomTheme, preserving its exact palette (0xFF09090Bsurface,0xFF6366F1primary,0xFF14141Asecondary) and its type scale.- The dev inspector's tab strip is now token-themed via
BloomTabs; its MateriallabelColor/indicatorColoroverrides no longer apply.
Fixed #
- The native text input's focus ring was previously drawn by Material's
focusedBorder. It is preserved via the newBloomEditableField.focusedDecoration. - The OTA update banner's download indicator is determinate again — it fills with real download progress rather than spinning indefinitely.
0.3.1 #
Fixed #
- Bumped
bloom_serverdependency constraint from^0.1.0to^0.2.0— the stale constraint was incompatible with any sibling package (bloom_cache,bloom_i18n) requiringbloom_server ^0.2.0, breakingpub getin any app combining them.
Added #
- Fabric-Grade Native Mobile AST Engine (
bloom_mobile.dart):BloomFlexLayout&RenderBloomFlex: Multi-pass Flexbox layout solver resolving flex-wrap, percentage dimensions, margins, and paddings on mobile devices.BloomLeafRenderBox&RenderBloomLeafText: Direct GPU canvas signal painter bypassing widget tree rebuilds on state changes.BloomNativeInputHost: Persistent native text controller bridge preserving keyboard insets and cursor selections.BloomVirtualList: Viewport sliver recycling forForEachNode.BloomMobileApp&runBloomMobile: Root mobile application wrapper mounting pure-Dart AST descriptor trees.
0.3.0 #
Added #
- Automatic OpenAPI 3.1 & Swagger / Scalar Documentation:
BloomApiRouternow includesenableOpenApi()andtoOpenApiSpec()for zero-config, single-line API documentation generation. The router automatically discovers registered routes, parameters, HTTP methods, and tags, rendering interactive Scalar (/api/docs) and Swagger UI (/api/swagger) consoles with official Bloom vector branding and dark mode styling. - HTTP HEAD Method Support for GET Routes:
BloomApiRouternow transparently supportsHEADrequests on allGETendpoints, returning accurate headers and status codes without body serialization.
Changed #
- Bloom API Router Specificity & Regex Matching: Fixed root
/path matching and wildcard resolution.
Added #
- Prerender readiness signal for headless-browser SSG/SSR:
BloomAppnow enables Flutter's semantics/accessibility tree and signalswindow.__BLOOM_PRERENDER_READY__after its first frame, on web only (no-op elsewhere). This is consumed bybloom_cli's new real headless-Chromium prerendering pipeline (bloom build web --static/--server) to know when a page has actually finished rendering before capturing its DOM.
0.2.2 #
Fixed #
BloomRequest.paramsdefaulted to aconst {}map: any middleware that tried to attach convenience context (e.g.bloom_i18n's resolved locale,bloom_auth_server's verifiedauth_user_id/auth_roles) on a request with no path parameters crashed withUnsupported operation: Cannot modify unmodifiable mapthe moment it ran.paramsnow always defaults to a fresh mutable map.BloomApiRouterdiscarded per-request middleware context on every route match: route dispatch built a newBloomRequestviacopyWith(params: ...)after global middlewares had already run and attached state (params, or framework-internalExpando-backed context) to the original request instance — silently dropping it before route-specific middlewares and the handler ever saw it. Path parameters are now merged into the same request instance in place, so global middleware state (locale resolution, auth claims, etc.) survives all the way to the handler.- A pure-Dart server importing
bloom_server.darttransitively pulled inpackage:flutter:bloom_realtime's single barrel exported both server-side (BloomChannelHub) and Flutter-app-only (RealtimeQueryBridge, which depends onBloomData'ssignals_flutter-backed reactivity) code together, so any backend depending on it could not run under a plaindart run/dart compile. Split intobloom_realtime.dart(server-safe) andbloom_realtime_client.dart(Flutter client extras). Added a new Flutter-independentbloom_core.dartbarrel (env config, DI container, logger) re-exported frombloom_server.dart, and abloom_data.dartbarrel for the client query/cache layer — server code should never importbloom.dartdirectly.
0.2.1 #
Fixed #
BloomEnvcrashed on first read of any unset key:get/getOrNull/getInt/getDouble/getBool/containsfell back tobool.hasEnvironment(key)with a runtimekey, but that constructor only accepts a compile-time constant — every call threwbool.hasEnvironment can only be used as a const constructorthe moment a requested key wasn't already loaded into the runtime map. Since routes commonly read config on their very first build, this could blank the initial frame. The dynamic dart-define fallback is removed; apps that need--dart-definevalues now seed them explicitly at boot via the newBloomEnv.loadDartDefines(...), using literal keys the same wayBloom.boot()already does forBLOOM_FLAVOR.- Scaffolded apps and the dev overlay showed a generic purple Material icon (
Icons.local_florist_rounded) instead of the Bloom brand mark: added a realBloomLogowidget that renders the actual five-petal gradient flower (matchingbloom-logo.tsx) and swapped it in across the CLI scaffold template, the dev inspector overlay, and both example apps.
0.2.0 #
Breaking #
- Canonical cache-key normalization:
BloomData.normalizeKeynow canonicalizes recursively —Mapsegments have their entries sorted, andIterablesegments are canonicalized element-wise. Keys whose map segments differed only by insertion order previously resolved to different cache slots and now correctly resolve to the same one. Any code that persisted or compared the raw output ofnormalizeKeymust be re-keyed.
Fixed #
- Invalidation reached only cached queries:
BloomData.invalidateQueriessignalled only queries that already held a cache entry, so a query that had never completed a successful fetch (still loading, or in the error state) was never notified. Callinginvalidate()on a failed query is now a working retry path. Prefix matching is evaluated on:segment boundaries, so['users']matches['users','detail','42']but not['usersettings','1']. - Garbage collection could deafen live queries: expired entries were evicted and their invalidation stream controllers closed without regard for active subscribers, permanently stopping a mounted query from receiving invalidations. Eviction now requires a zero listener count, and a controller is never closed while a listener is attached. The same guard now covers
getEntry(),getQueryData()andremoveEntry(), which each closed controllers as a side effect of reading or removing an expired entry.
Added #
BloomData.releaseListener(key): releases a listener slot acquired viaBloomData.onInvalidated(key).BloomQuery.dispose()calls it automatically, so it is only needed when subscribing toonInvalidateddirectly.
0.1.0 #
- Core Runtime & Boot Lifecycle: Single-call
Bloom.boot()with dependency injection container (inject<T>(),provideSingleton<T>()). - Signals State Management: High-performance fine-grained reactivity (
signal,computed,effect,batch,Watch,SignalBuilder). - Filesystem Routing: File-based route conventions (
index.dart,[id].dart,_layout.dartShellRoutes, route guards). - Bloom Data & Offline Engine: Stale-while-revalidate caching (
BloomData.query,BloomData.mutation), deduplication, TTL GC, andOfflineMutationQueue. - Native Architecture & Prebuild: Declarative native plugin integrations (
BloomPermissions,BloomSecureStorage,BloomNotifications,BloomCamera,BloomDeepLinks). - DevTools & Dev Server: UDP broadcast discovery on port 5354, visual DevTools overlay,
BloomNetworkInspectorwith request replay. - Full-Stack Server & SSR Engine:
BloomApiRouter,BloomRequest,BloomResponse, API route handlers, and middleware. - Observability & Error Telemetry: Automatic crash capture, breadcrumbs timeline, symbol packaging, and fingerprinting.
- Full-Stack Adapters: Official Supabase and Serverpod client & repository adapters.