Skip to content

Commit 4ea5c2e

Browse files
authored
chore(release): 1.0.0-alpha.7 (#39)
* chore(release): 1.0.0-alpha.7 Broadcasting module (Echo facade, BroadcastManager, ReverbBroadcastDriver), router observers, network driver plugin hook, custom log drivers. Updates: facade count 16→17, test count 453→858, CHANGELOG PR refs, docs/skills/README synced with Echo facade and broadcasting docs. * fix(docs): address PR #39 review feedback - Add missing `late FakeBroadcastManager echoFake` declaration - Fix Echo.fake() example: connect before assertConnected, disconnect before assertDisconnected - Fix Echo.listen callback type: `void Function(BroadcastEvent)` not `Function(BroadcastEvent)` - Reword "All facades" → "The following facades" for fake/unfake list
1 parent 5059146 commit 4ea5c2e

10 files changed

Lines changed: 75 additions & 18 deletions

File tree

.github/copilot-instructions.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ lib/
1414
├── config/ # Default configs
1515
└── src/
1616
├── foundation/ # MagicApp (IoC), Magic (bootstrap), ConfigRepository, Env
17-
├── facades/ # 16 facades: Auth, Cache, Config, Crypt, DB, Event, Gate, Http, Lang, Launch, Log, Pick, Route, Schema, Storage, Vault
17+
├── facades/ # 17 facades: Auth, Cache, Config, Crypt, DB, Echo, Event, Gate, Http, Lang, Launch, Log, Pick, Route, Schema, Storage, Vault
1818
├── auth/ # AuthManager, guards, events
19+
├── broadcasting/ # BroadcastManager, Echo facade, Reverb/Null drivers
1920
├── cache/ # CacheManager, drivers (memory, file)
2021
├── database/ # Eloquent ORM, QueryBuilder, migrations, seeders, factories
2122
├── http/ # MagicController, middleware pipeline, Kernel
@@ -48,7 +49,7 @@ lib/
4849
| Facade call before `Magic.init()` | Always `await Magic.init()` in `main()` first |
4950
| Missing `Auth.manager.setUserFactory()` | Must call in boot phase |
5051
| Forgetting test reset | `MagicApp.reset()` + `Magic.flush()` in every `setUp()` |
51-
| `EncryptionServiceProvider` / `LaunchServiceProvider` | NOT auto-registered -- add explicitly |
52+
| `BroadcastServiceProvider` / `EncryptionServiceProvider` / `LaunchServiceProvider` | NOT auto-registered -- add explicitly |
5253
| `ValidatesRequests` import | Lives in `concerns/`, not `http/` |
5354
| `Event.register()` takes factories | `List<Listener Function()>`, not listener instances |
5455

CHANGELOG.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
All notable changes to this project will be documented in this file.
44

5-
## [Unreleased]
5+
## [1.0.0-alpha.7] - 2026-04-06
66

77
### ✨ Features
8-
- **Broadcasting**: `Echo` facade, `BroadcastManager`, `ReverbBroadcastDriver` (Pusher-compatible WebSocket with reconnection, dedup, heartbeat), `NullBroadcastDriver`, `BroadcastInterceptor` pipeline, `FakeBroadcastManager`, `BroadcastServiceProvider`. Laravel Echo equivalent for real-time channels. (#37)
9-
- **Router Observers**: `MagicRouter.instance.addObserver()` enables NavigatorObserver integration for analytics/monitoring (Sentry, Firebase Analytics, custom observers). Observers are passed to GoRouter automatically. (#31)
10-
- **Network Driver Plugin Hook**: `DioNetworkDriver.configureDriver()` exposes the underlying Dio instance for SDK integrations (sentry_dio, certificate pinning, custom adapters). (#32)
11-
- **Custom Log Drivers**: `LogManager.extend()` enables custom LoggerDriver registration (Sentry, file, Slack). Config-driven resolution with built-in override support. (#33)
8+
- **Broadcasting**: `Echo` facade, `BroadcastManager`, `ReverbBroadcastDriver` (Pusher-compatible WebSocket with reconnection, dedup, heartbeat), `NullBroadcastDriver`, `BroadcastInterceptor` pipeline, `FakeBroadcastManager`, `BroadcastServiceProvider`. Laravel Echo equivalent for real-time channels. (#38)
9+
- **Router Observers**: `MagicRouter.instance.addObserver()` enables NavigatorObserver integration for analytics/monitoring (Sentry, Firebase Analytics, custom observers). Observers are passed to GoRouter automatically. (#34)
10+
- **Network Driver Plugin Hook**: `DioNetworkDriver.configureDriver()` exposes the underlying Dio instance for SDK integrations (sentry_dio, certificate pinning, custom adapters). (#35)
11+
- **Custom Log Drivers**: `LogManager.extend()` enables custom LoggerDriver registration (Sentry, file, Slack). Config-driven resolution with built-in override support. (#36)
1212

1313
## [1.0.0-alpha.6] - 2026-04-05
1414

CLAUDE.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ Laravel-inspired Flutter framework with Facades, Eloquent ORM, Service Providers
2424
```
2525
lib/
2626
├── magic.dart # Barrel export (public API)
27-
├── config/ # Default configs (app, auth, cache, database, view)
27+
├── config/ # Default configs (app, auth, broadcasting, cache, database, view)
2828
└── src/
2929
├── foundation/ # MagicApp (IoC), Magic (bootstrap), ConfigRepository, Env
30-
├── facades/ # 16 facades: Auth, Cache, Config, Crypt, DB, Event, Gate, Http, Lang, Launch, Log, Pick, Route, Schema, Storage, Vault
30+
├── facades/ # 17 facades: Auth, Cache, Config, Crypt, DB, Echo, Event, Gate, Http, Lang, Launch, Log, Pick, Route, Schema, Storage, Vault
3131
├── auth/ # AuthManager, guards (Bearer, BasicAuth, ApiKey), events
32+
├── broadcasting/ # BroadcastManager, Echo facade, Reverb/Null drivers, interceptors
3233
├── cache/ # CacheManager, drivers (memory, file)
3334
├── database/ # Eloquent ORM, QueryBuilder, migrations, seeders, factories
3435
├── encryption/ # EncryptionServiceProvider (NOT auto-registered)
@@ -71,7 +72,7 @@ This project follows strict **Test-Driven Development**. Every feature, fix, or
7172

7273
**Rules:**
7374
- No production code without a failing test first
74-
- Run `flutter test` after every change — all 453+ tests must stay green
75+
- Run `flutter test` after every change — all 858+ tests must stay green
7576
- Run `dart analyze` after every change — zero warnings, zero errors
7677
- Run `dart format .` before committing — zero formatting issues
7778
- `dart pub publish --dry-run` must pass before any release
@@ -93,7 +94,7 @@ This project follows strict **Test-Driven Development**. Every feature, fix, or
9394
| Facade call before `Magic.init()` | Always `await Magic.init()` in `main()` first |
9495
| Missing `Auth.manager.setUserFactory()` | Must call in boot phase — auth won't work without it |
9596
| Forgetting test reset | `MagicApp.reset()` + `Magic.flush()` in every `setUp()` |
96-
| `EncryptionServiceProvider` / `LaunchServiceProvider` | NOT auto-registered — add explicitly to config providers |
97+
| `BroadcastServiceProvider` / `EncryptionServiceProvider` / `LaunchServiceProvider` | NOT auto-registered — add explicitly to config providers |
9798
| `configFactories` vs `configs` param | Use `configFactories` for configs needing `Env.get()` |
9899
| `Event.register()` takes factories | `List<Listener Function()>`, not listener instances |
99100
| `routerConfig` before init | Only accessible after `Magic.init()` completes |

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ final user = await User.find(1);
4949
| | Feature | Description |
5050
|:--|:--------|:------------|
5151
| 🏗️ | **IoC Container** | Service Container with singleton, bind, and instance registration |
52-
| 🎭 | **16 Facades** | `Auth`, `Http`, `Cache`, `DB`, `Event`, `Gate`, `Log`, `Route`, `Lang`, `Storage`, `Vault`, `Crypt` and more |
52+
| 🎭 | **17 Facades** | `Auth`, `Http`, `Cache`, `DB`, `Echo`, `Event`, `Gate`, `Log`, `Route`, `Lang`, `Storage`, `Vault`, `Crypt` and more |
5353
| 🗄️ | **Eloquent ORM** | Models, QueryBuilder, migrations, seeders, factories — hybrid API + SQLite persistence |
5454
| 🛣️ | **Routing** | GoRouter integration with middleware, named routes, and context-free navigation |
5555
| 🔐 | **Authentication** | Token-based auth with guards (Bearer, BasicAuth, ApiKey), session restore, auto-refresh |
@@ -423,7 +423,7 @@ void main() {
423423
}
424424
```
425425

426-
All facades support `fake()` / `unfake()`: `Http`, `Auth`, `Cache`, `Vault`, `Log`. Each fake records operations and exposes assertion helpers.
426+
The following facades support `fake()` / `unfake()`: `Http`, `Auth`, `Cache`, `Vault`, `Log`, `Echo`. Each fake records operations and exposes assertion helpers.
427427

428428
## Architecture
429429

@@ -433,7 +433,7 @@ Magic.init() → Env.load() → configFactories → providers register() → pro
433433

434434
```
435435
lib/
436-
├── config/ # Configuration files (app, auth, cache, database)
436+
├── config/ # Configuration files (app, auth, broadcasting, cache, database)
437437
├── app/
438438
│ ├── controllers/ # Request handlers (MagicController)
439439
│ ├── models/ # Eloquent models
@@ -462,6 +462,7 @@ Full docs at **[magic.fluttersdk.com](https://magic.fluttersdk.com)**.
462462
| [HTTP Client](https://magic.fluttersdk.com/basics/http-client) | Network requests |
463463
| [Middleware](https://magic.fluttersdk.com/basics/middleware) | Request pipeline |
464464
| [Forms](https://magic.fluttersdk.com/basics/forms) | Form handling and validation |
465+
| [Broadcasting](https://magic.fluttersdk.com/digging-deeper/broadcasting) | Real-time WebSocket channels |
465466

466467
## AI Agent Integration
467468

example/pubspec.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ packages:
507507
path: ".."
508508
relative: true
509509
source: path
510-
version: "1.0.0-alpha.6"
510+
version: "1.0.0-alpha.7"
511511
magic_cli:
512512
dependency: transitive
513513
description:

example/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ dependencies:
3636
cupertino_icons: ^1.0.9
3737
magic:
3838
path: ..
39-
version: 1.0.0-alpha.6
39+
version: 1.0.0-alpha.7
4040

4141
dev_dependencies:
4242
flutter_test:

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: magic
22
description: "A Laravel-inspired Flutter framework with Eloquent ORM, routing, and MVC architecture."
3-
version: 1.0.0-alpha.6
3+
version: 1.0.0-alpha.7
44
homepage: https://magic.fluttersdk.com
55
repository: https://github.com/fluttersdk/magic
66
issue_tracker: https://github.com/fluttersdk/magic/issues

skills/magic-framework/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ Official plugins extending Magic Framework. Each has its own package, service pr
617617
| File | Content | Load When |
618618
|------|---------|-----------|
619619
| `references/bootstrap-lifecycle.md` | Magic.init 7-step sequence, IoC API, ServiceProvider register/boot, Env/Config, Kernel, MagicApplication | Setting up app bootstrap, creating providers, or configuring environment |
620-
| `references/facades-api.md` | All 16 facades with method signatures and return types | Looking up any facade method signature or return type |
620+
| `references/facades-api.md` | All 17 facades with method signatures and return types | Looking up any facade method signature or return type |
621621
| `references/eloquent-orm.md` | Model definition, attributes, casts, relations, `InteractsWithPersistence`, QueryBuilder, migrations, Blueprint | Working with models, database queries, or migrations |
622622
| `references/controllers-views.md` | MagicController, MagicStateMixin, RxStatus, MagicView, MagicStatefulView, MagicStatefulViewState, MagicResponsiveView, MagicBuilder, MagicCan/MagicCannot | Building controllers or views, reactive state, authorization widgets |
623623
| `references/forms-validation.md` | MagicFormData, MagicForm, rules(), FormValidator, ValidatesRequests, built-in rules (Required, Email, Min, Max, Confirmed, Same, Accepted), process(), processingListenable | Building forms, adding validation, handling server-side errors |

skills/magic-framework/references/facades-api.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,30 @@ await DB.transaction(() async {
188188

189189
---
190190

191+
## Echo
192+
193+
Proxies to `BroadcastManager` for real-time WebSocket communication. `BroadcastServiceProvider` must be registered explicitly.
194+
195+
| Signature | Return Type | Notes |
196+
|-----------|-------------|-------|
197+
| `Echo.channel(String name)` | `BroadcastChannel` | Subscribe to a public channel. |
198+
| `Echo.private(String name)` | `BroadcastChannel` | Subscribe to a private channel (auth required). |
199+
| `Echo.join(String name)` | `BroadcastPresenceChannel` | Join a presence channel (auth + member tracking). |
200+
| `Echo.listen(String channel, String event, void Function(BroadcastEvent) callback)` | `BroadcastChannel` | Shorthand: subscribe + listen in one call. |
201+
| `Echo.leave(String name)` | `void` | Unsubscribe from a channel. |
202+
| `Echo.connect()` | `Future<void>` | Establish the WebSocket connection. |
203+
| `Echo.disconnect()` | `Future<void>` | Close connection and release resources. |
204+
| `Echo.connection` | `BroadcastDriver` | Resolved default driver instance. |
205+
| `Echo.socketId` | `String?` | Server-assigned socket ID; `null` when disconnected. |
206+
| `Echo.connectionState` | `Stream<BroadcastConnectionState>` | Stream of connection lifecycle state changes. |
207+
| `Echo.onReconnect` | `Stream<void>` | Emits once each successful reconnect. |
208+
| `Echo.addInterceptor(BroadcastInterceptor interceptor)` | `void` | Register an interceptor on the default connection. |
209+
| `Echo.manager` | `BroadcastManager` | Direct manager access for `extend()`. |
210+
| `Echo.fake()` | `FakeBroadcastManager` | Swap to in-memory fake for testing. |
211+
| `Echo.unfake()` | `void` | Restore real manager binding. |
212+
213+
---
214+
191215
## Event
192216

193217
Dispatches via `EventDispatcher.instance`. The `Event` facade only exposes `dispatch()` — listener registration is done directly on the dispatcher.

skills/magic-framework/references/testing-patterns.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,7 @@ late FakeAuthManager authFake;
612612
late FakeCacheManager cacheFake;
613613
late FakeVaultService vaultFake;
614614
late FakeLogManager logFake;
615+
late FakeBroadcastManager echoFake;
615616
616617
setUp(() {
617618
MagicApp.reset();
@@ -621,13 +622,15 @@ setUp(() {
621622
cacheFake = Cache.fake(); // In-memory cache, records operations
622623
vaultFake = Vault.fake(); // In-memory secure storage, no platform channels
623624
logFake = Log.fake(); // Captures log entries, no console output
625+
echoFake = Echo.fake(); // In-memory broadcasting, no WebSocket
624626
});
625627
626628
tearDown(() {
627629
Auth.unfake();
628630
Cache.unfake();
629631
Vault.unfake();
630632
Log.unfake();
633+
Echo.unfake();
631634
});
632635
```
633636

@@ -723,6 +726,33 @@ test('second test', () {
723726
});
724727
```
725728

729+
### Echo.fake()
730+
731+
```dart
732+
final fake = Echo.fake();
733+
734+
await Echo.connect();
735+
736+
Echo.channel('orders');
737+
Echo.private('user.1');
738+
739+
// Assertions while connected
740+
fake.assertConnected();
741+
fake.assertSubscribed('orders');
742+
fake.assertNotSubscribed('chat');
743+
fake.assertInterceptorAdded();
744+
745+
// Low-level driver access
746+
expect(fake.driver.subscribedChannels, contains('orders'));
747+
expect(fake.driver.subscribedChannels, contains('private-user.1'));
748+
749+
await Echo.disconnect();
750+
fake.assertDisconnected();
751+
752+
// Reset recorded state
753+
fake.reset();
754+
```
755+
726756
## Middleware Testing
727757

728758
Middleware is tested by verifying whether it calls `next()` or halts the pipeline.

0 commit comments

Comments
 (0)