mirror of
https://github.com/pese-git/cherrypick.git
synced 2026-01-23 21:13:35 +00:00
doc: update readme
This commit is contained in:
223
README.md
223
README.md
@@ -1,184 +1,145 @@
|
|||||||
# CherryPick Workspace
|
# CherryPick Workspace
|
||||||
|
|
||||||
CherryPick Workspace is a modular ecosystem for declarative, type-safe dependency injection in Dart and Flutter applications. It brings together core dependency management, advanced code generation, annotation-driven DI, and seamless Flutter integration for stateful, testable, and scalable app architectures.
|
CherryPick Workspace is a modular, open-source dependency injection ecosystem for Dart and Flutter, designed to offer lightweight, flexible, and scalable DI suitable for both backend and frontend (Flutter) development. This monorepo contains the main DI runtime library, annotation helpers, code generation for modular bindings, and seamless Flutter integration.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Overview
|
## Packages Overview
|
||||||
|
|
||||||
CherryPick Workspace includes the following packages:
|
- **[`cherrypick`](./cherrypick)**
|
||||||
|
The core dependency injection library. Supports modular bindings, hierarchical scopes, named and singleton bindings, provider functions (sync/async), runtime parameters, and test-friendly composition.
|
||||||
|
_Intended for use in pure Dart and Flutter projects._
|
||||||
|
|
||||||
- **`cherrypick`** – Core dependency injection engine for Dart: bindings, modules, scopes, and runtime resolution.
|
- **[`cherrypick_annotations`](./cherrypick_annotations)**
|
||||||
- **`cherrypick_annotations`** – Lightweight annotation library (`@module`, `@singleton`, `@named`) for injectable code and code generation.
|
A set of Dart annotations (`@module`, `@singleton`, `@instance`, `@provide`, `@named`, `@params`) enabling concise, declarative DI modules and providers, primarily for use with code generation tools.
|
||||||
- **`cherrypick_generator`** – Code generator that produces DI module boilerplate from annotated Dart classes, using `cherrypick_annotations`.
|
|
||||||
- **`cherrypick_flutter`** – Flutter integration providing scope-aware dependency resolution via `CherryPickProvider` in the widget tree.
|
- **[`cherrypick_generator`](./cherrypick_generator)**
|
||||||
|
A [source_gen](https://pub.dev/packages/source_gen)-based code generator that automatically converts your annotated modules and providers into ready-to-use boilerplate for registration and resolution within your app.
|
||||||
|
_Reduces manual wiring and errors; compatible with build_runner._
|
||||||
|
|
||||||
|
- **[`cherrypick_flutter`](./cherrypick_flutter)**
|
||||||
|
Adds Flutter-native integration, exposing DI scopes and modules to the widget tree through `CherryPickProvider` and enabling dependency management throughout your Flutter app.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Repository Structure
|
## Why CherryPick?
|
||||||
|
|
||||||
- `cherrypick/` – Core DI library (bindings, modules, scopes, runtime resolution)
|
- **Zero-overhead and intuitive API:**
|
||||||
- `cherrypick_annotations/` – DI annotations for use with generators
|
Clean, minimal syntax, strong typing, powerful binding lifecycle control.
|
||||||
- `cherrypick_generator/` – Source-gen implementation for codegen of modules and bindings
|
- **High testability:**
|
||||||
- `cherrypick_flutter/` – Flutter tools to provide DI in widget subtree via `CherryPickProvider`
|
Supports overriding and hierarchical scope trees.
|
||||||
- `examples/` – Sample Flutter projects demonstrating patterns
|
- **Both Sync & Async support:**
|
||||||
|
Register and resolve async providers, factories, and dependencies.
|
||||||
|
- **Seamless code generation:**
|
||||||
|
Effortless setup with annotations + generator—skip boilerplate!
|
||||||
|
- **Works with or without Flutter.**
|
||||||
|
- **Production ready:**
|
||||||
|
Robust enough for apps, packages, and server-side Dart.
|
||||||
|
- **Extensible & Modular:**
|
||||||
|
Add bindings at runtime, use sub-modules, or integrate via codegen.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Quick Start Guide
|
## Get Started
|
||||||
|
|
||||||
### Installation
|
### 1. Add dependencies
|
||||||
|
|
||||||
Add the desired packages to your `pubspec.yaml` (pick what you need):
|
In your `pubspec.yaml`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
dependencies:
|
dependencies:
|
||||||
cherrypick: ^latest
|
cherrypick: ^<latest-version>
|
||||||
cherrypick_annotations: ^latest
|
cherrypick_annotations: ^<latest-version>
|
||||||
cherrypick_flutter: ^latest
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
cherrypick_generator: ^latest
|
build_runner: ^<latest>
|
||||||
build_runner: ^latest
|
cherrypick_generator: ^<latest-version>
|
||||||
```
|
```
|
||||||
|
|
||||||
Run `flutter pub get` or `dart pub get` to fetch dependencies.
|
For Flutter projects, add:
|
||||||
|
|
||||||
---
|
```yaml
|
||||||
|
dependencies:
|
||||||
|
cherrypick_flutter: ^<latest-version>
|
||||||
|
```
|
||||||
|
|
||||||
### Usage
|
### 2. Write a DI Module (with annotations)
|
||||||
|
|
||||||
#### Core DI (`cherrypick`)
|
```dart
|
||||||
|
import 'package:cherrypick_annotations/cherrypick_annotations.dart';
|
||||||
|
import 'package:cherrypick/cherrypick.dart';
|
||||||
|
|
||||||
- **Bind dependencies:**
|
@module()
|
||||||
|
abstract class MyModule extends Module {
|
||||||
```dart
|
|
||||||
Binding<String>().toInstance("hello world");
|
|
||||||
Binding<ApiClient>().toProvide(() => ApiClientImpl()).singleton();
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Module definition:**
|
|
||||||
|
|
||||||
```dart
|
|
||||||
class AppModule extends Module {
|
|
||||||
@override
|
|
||||||
void builder(Scope currentScope) {
|
|
||||||
bind<ApiClient>().toInstance(ApiClientMock());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Scope management:**
|
|
||||||
|
|
||||||
```dart
|
|
||||||
final rootScope = CherryPick.openRootScope();
|
|
||||||
rootScope.installModules([AppModule()]);
|
|
||||||
final client = rootScope.resolve<ApiClient>();
|
|
||||||
```
|
|
||||||
|
|
||||||
You can create sub-scopes for feature isolation as needed:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
final featureScope = rootScope.openSubScope("feature");
|
|
||||||
featureScope.installModules([FeatureModule()]);
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Annotation & Code Generation (`cherrypick_annotations`, `cherrypick_generator`)
|
|
||||||
|
|
||||||
- **Annotate your DI modules:**
|
|
||||||
|
|
||||||
```dart
|
|
||||||
import 'package:cherrypick_annotations/cherrypick_annotations.dart';
|
|
||||||
import 'package:cherrypick/cherrypick.dart';
|
|
||||||
|
|
||||||
part 'app_module.cherrypick.g.dart';
|
|
||||||
|
|
||||||
@module()
|
|
||||||
abstract class AppModule extends Module {
|
|
||||||
@singleton()
|
@singleton()
|
||||||
ApiClient client() => ApiClientImpl();
|
ApiClient apiClient() => ApiClient();
|
||||||
|
|
||||||
@named('apiBaseUrl')
|
@provide()
|
||||||
String baseUrl() => 'https://api.example.com';
|
DataRepository dataRepo(ApiClient client) => DataRepository(client);
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Generate code:**
|
@provide()
|
||||||
|
String greeting(@params() String name) => 'Hello, $name!';
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Run:
|
### 3. Generate the bindings
|
||||||
|
|
||||||
```shell
|
```sh
|
||||||
dart run build_runner build
|
dart run build_runner build
|
||||||
```
|
# or for Flutter:
|
||||||
|
flutter pub run build_runner build
|
||||||
|
```
|
||||||
|
|
||||||
This will generate efficient registration code for your modules.
|
The generator will create a `$MyModule` class with binding code.
|
||||||
|
|
||||||
#### Flutter Integration (`cherrypick_flutter`)
|
### 4. Install and Resolve
|
||||||
|
|
||||||
- **Setup `CherryPickProvider` in your widget tree:**
|
```dart
|
||||||
|
final scope = CherryPick.openRootScope()
|
||||||
|
..installModules([$MyModule()]);
|
||||||
|
|
||||||
```dart
|
final repo = scope.resolve<DataRepository>();
|
||||||
void main() {
|
final greeting = scope.resolveWithParams<String>('John'); // 'Hello, John!'
|
||||||
|
```
|
||||||
|
|
||||||
|
_For Flutter, wrap your app with `CherryPickProvider` for DI scopes in the widget tree:_
|
||||||
|
|
||||||
|
```dart
|
||||||
|
void main() {
|
||||||
runApp(
|
runApp(
|
||||||
CherryPickProvider(
|
CherryPickProvider(child: MyApp()),
|
||||||
child: MyApp(),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- **Access DI scopes anywhere in Flutter:**
|
|
||||||
|
|
||||||
```dart
|
|
||||||
class MyWidget extends StatelessWidget {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final cherryPick = CherryPickProvider.of(context);
|
|
||||||
final rootScope = cherryPick.openRootScope();
|
|
||||||
|
|
||||||
final repo = rootScope.resolve<MyRepository>();
|
|
||||||
// use repo as needed...
|
|
||||||
|
|
||||||
return Text('Dependency resolved!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Features
|
## Features at a Glance
|
||||||
|
|
||||||
- [x] Module-based configuration & composition
|
- ⚡ **Fast, lightweight DI** for any Dart/Flutter project
|
||||||
- [x] Flexible scopes (main/root/subscopes)
|
- 🧩 **Modular & hierarchical scopes** (root, subscopes)
|
||||||
- [x] Named and singleton bindings
|
- 🔖 **Named/bound/singleton instances** out of the box
|
||||||
- [x] Async binding and parameter injection
|
- 🔄 **Sync and async provider support**
|
||||||
- [x] Annotations (`@module`, `@singleton`, `@named`) for concise setup
|
- ✏️ **Runtime parameters for dynamic factory methods**
|
||||||
- [x] Code generation for efficient, boilerplate-free DI modules
|
- 🏷️ **Code generator** for annotation-based DI setup (`cherrypick_generator`)
|
||||||
- [x] Seamless integration with Flutter via InheritedWidget (`CherryPickProvider`)
|
- 🕹️ **Deep Flutter integration** via `CherryPickProvider`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Example Projects
|
## Example Usage
|
||||||
|
|
||||||
See the [`examples/`](examples/) directory for real-world usage patterns, including synchronous, asynchronous, and named injection in Flutter apps.
|
Please see:
|
||||||
|
- [`cherrypick/README.md`](./cherrypick/README.md) for core DI features and examples
|
||||||
|
- [`cherrypick_flutter/README.md`](./cherrypick_flutter/README.md) for Flutter-specific usage
|
||||||
|
- [`cherrypick_annotations/README.md`](./cherrypick_annotations/README.md) and [`cherrypick_generator/README.md`](./cherrypick_generator/README.md) for codegen and annotations
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Contributing
|
## Contribution & License
|
||||||
|
|
||||||
Community feedback, bug reports, and PRs are welcome! Please file issues and suggestions on the [GitHub issues page](https://github.com/pese-git/cherrypick/issues).
|
- **Contributions:** PRs, issues, and feedback are welcome on [GitHub](https://github.com/pese-git/cherrypick).
|
||||||
|
- **License:** Apache 2.0 for all packages in this workspace.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## License
|
**Happy Cherry Picking! 🍒**
|
||||||
|
|
||||||
CherryPick Workspace is licensed under the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Links
|
|
||||||
|
|
||||||
- [CherryPick GitHub Repository](https://github.com/pese-git/cherrypick)
|
|
||||||
- [cherrypick_flutter on pub.dev](https://pub.dev/packages/cherrypick_flutter)
|
|
||||||
- [cherrypick_generator on pub.dev](https://pub.dev/packages/cherrypick_generator)
|
|
||||||
- [cherrypick_annotations on pub.dev](https://pub.dev/packages/cherrypick_annotations)
|
|
||||||
Reference in New Issue
Block a user