aegis_honeycomb 1.0.3 copy "aegis_honeycomb: ^1.0.3" to clipboard
aegis_honeycomb: ^1.0.3 copied to clipboard

A simple, type-safe, codegen-free Flutter state management library with clear State/Effect separation, auto dependency tracking, and powerful Scope/Override mechanism.

๐Ÿฏ Honeycomb #

English | ็ฎ€ไฝ“ไธญๆ–‡

Pub Version Flutter License: MIT

Concise, type-safe, codegen-free state management library for Flutter.

Honeycomb provides clear separation between State and Effect semantics, automatic dependency tracking, and a powerful Scope/Override mechanism.


โœจ Features #

  • ๐ŸŽฏ Context-Free Usage โ€” Access state in pure Dart logic (Services/Repositories) via Global Container.
  • โšก Auto Dependency Tracking โ€” Computed automatically tracks dependencies from watch.
  • ๐Ÿ“ก State vs Effect โ€” Clearly distinguish between replayable state and one-time events.
  • ๐ŸŽญ Scope/Override โ€” Flexible dependency injection and local overrides.
  • ๐Ÿ”„ No Codegen โ€” Pure Dart, no build_runner required.
  • ๐Ÿ”’ Type Safe โ€” Full generic support.
  • ๐Ÿงช Easy to Test โ€” Decouple state logic from UI for easy testing.

๐Ÿ“ฆ Installation #

dependencies:
  honeycomb: ^1.0.0
flutter pub get

๐Ÿš€ Quick Start #

1. Define State #

import 'package:aegis_honeycomb/honeycomb.dart';

// Read-write state
final counterState = StateRef(0);

// Derived state (auto dependency tracking)
final doubledCounter = Computed((watch) => watch(counterState) * 2);

// Async state
final userProfile = Computed.async((watch) async {
  final userId = watch(currentUserId);
  return await api.fetchUser(userId);
});

// One-time events
final toastEffect = Effect<String>();

2. Provide Container #

// You can keep a global container if you don't want to rely on BuildContext.
final appContainer = HoneycombContainer();

void main() {
  runApp(
    HoneycombScope(
      container: appContainer,
      child: MyApp(),
    ),
  );
}

3. Use in UI #

class CounterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return HoneycombConsumer(
      builder: (context, ref, child) {
        final count = ref.watch(counterState);
        final doubled = ref.watch(doubledCounter);

        return Column(
          children: [
            Text('Count: $count'),
            Text('Doubled: $doubled'),
            ElevatedButton(
              onPressed: () {
                final container = HoneycombScope.readOf(context);
                container.write(counterState, count + 1);
              },
              child: Text('Increment'),
            ),
          ],
        );
      },
    );
  }
}

๐Ÿ“š Documentation #

Document Description
Getting Started Learn Honeycomb from scratch
Core Concepts Deep dive into design philosophy
API Reference Full API documentation
Best Practices Recommended usage patterns
Comparison Comparison with Provider/Riverpod/Bloc
FAQ Frequently Asked Questions

๐ŸŽฏ Core Concepts at a Glance #

State vs Effect #

// State: Replayable, always returns the latest value
final userName = StateRef('Guest');

// Effect: One-time event, no historical storage
final showToast = Effect<String>(strategy: EffectStrategy.drop);

Dependency Tracking #

final fullName = Computed((watch) {
  // Automatically tracks firstName and lastName
  return '${watch(firstName)} ${watch(lastName)}';
});
// fullName recalculates whenever firstName or lastName changes

Scope Override #

HoneycombScope supports overriding state values in a subtree using the overrides parameter. This is extremely useful for testing (Mocking) or parameterizing child components.

How it works: When resolving an Atom, the container first checks if it's in overrides; if not, it looks up the parent container; finally, it creates a new node based on the default logic.

// Locally override state (e.g., for testing or theme switching)
HoneycombScope(
  overrides: [
    // Force themeState to be dark
    themeState.overrideWith(ThemeData.dark()),

    // Or override an async state with mock data
    userProfile.overrideWith(AsyncValue.data(MockUser())),
  ],
  child: DarkModePage(),
)

Using in Business Logic (Outside Context) #

Sometimes you need to access state in Repositories, Services, or pure Dart logic.

1. Create a Global Container (e.g. in app_globals.dart)

// Global singleton container
final appContainer = HoneycombContainer();

2. Use directly in Services

class AuthService {
  void logout() {
    // Read state
    final currentUser = appContainer.read(userState);
    
    // Write state
    appContainer.write(userState, null);
    
    // Emit event
    appContainer.emit(navigationEffect, '/login');
  }
}

3. Inject into UI Tree

void main() {
  runApp(
    HoneycombScope(
      container: appContainer, // Must inject the same instance for UI updates
      child: MyApp(),
    ),
  );
}

๐Ÿงช Testing #

test('counter increments', () {
  final container = HoneycombContainer();
  
  expect(container.read(counterState), 0);
  
  container.write(counterState, 1);
  
  expect(container.read(counterState), 1);
  expect(container.read(doubledCounter), 2);
});

๐Ÿ“Š Comparison #

Feature Honeycomb Provider Riverpod Bloc
No Codegen โœ… โœ… โŒ โœ…
Auto Tracking โœ… โŒ โœ… โŒ
State/Effect Separation โœ… โŒ โŒ โœ…
Scope Override โœ… โœ… โœ… โŒ
Batch Updates โœ… โŒ โŒ โœ…
Learning Curve Low Low Medium High

๐Ÿค Contributing #

Contributions are welcome! Please check CONTRIBUTING.md.


๐Ÿ“„ License #

MIT License - See the LICENSE file.

1
likes
150
points
286
downloads

Publisher

verified publisheraegis-labs.com

Weekly Downloads

A simple, type-safe, codegen-free Flutter state management library with clear State/Effect separation, auto dependency tracking, and powerful Scope/Override mechanism.

Repository (GitHub)
View/report issues

Topics

#state-management #flutter #reactive #dependency-injection

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on aegis_honeycomb