diff --git a/cherrypick_annotations/example/example.dart b/cherrypick_annotations/example/example.dart new file mode 100644 index 0000000..da876e4 --- /dev/null +++ b/cherrypick_annotations/example/example.dart @@ -0,0 +1,111 @@ +// ignore: dangling_library_doc_comments +/// Example using cherrypick_annotations together with cherrypick (core) and cherrypick_generator. + +/// +/// Steps to use this example: +/// 1. Make sure your example/pubspec.yaml contains: +/// - cherrypick_annotations (this package) +/// - cherrypick (core DI engine) +/// - cherrypick_generator (as a dev_dependency) +/// - build_runner (as a dev_dependency) +/// 2. Run code generation to produce DI injectors and mixins: +/// ```sh +/// dart run build_runner build +/// ``` +/// 3. The `_$ApiScreen` mixin will be generated automatically. +/// 4. In your app/bootstrap code, install modules and use the generated features. +/// +/// See documentation and advanced details at: +/// https://pub.dev/packages/cherrypick_annotations + +import 'package:cherrypick_annotations/cherrypick_annotations.dart'; +// In a real project, use this import: +// import 'package:cherrypick/cherrypick.dart'; + +// Temporary stub for demonstration purposes only. +// In real usage, import 'Module' from `package:cherrypick/cherrypick.dart`. +class Module {} + +/// This mixin is a stub for documentation and IDE hints only. +/// In a real project, it will be generated by cherrypick_generator after running build_runner. +/// +/// Do not implement or edit this by hand! +mixin _$ApiScreen {} + +/// Example UI/service class with dependencies to be injected. +/// +/// The [@injectable] annotation tells the generator to create an injector mixin for this class. +/// Fields marked with [@inject] will be automatically filled by the code generator (using DI). +@injectable() +class ApiScreen with _$ApiScreen { + /// The default (main) implementation of the API service. + @inject() + late final ApiService apiService; + + /// An alternate API (mock) implementation, injected by name using @named. + @inject() + @named('mock') + late final ApiService mockApiService; + + /// Logger injected from another scope (e.g., global singleton). + @inject() + @scope('global') + late final Logger logger; +} + +/// Example DI module using CherryPick annotations. +/// +/// The [@module] annotation tells the generator to treat this class as a source of bindings. +/// Methods annotated with [@singleton], [@named], [@provide], [@instance] will be registered into the DI container. +@module() +abstract class AppModule extends Module { + /// Global singleton logger available throughout the app. + @singleton() + Logger provideLogger() => Logger(); + + /// Main API implementation, identified with the name 'main'. + @named('main') + ApiService createApi() => ApiService(); + + /// Mock API implementation, identified as 'mock'. + @named('mock') + ApiService createMockApi() => MockApiService(); + + /// UserManager is created with runtime parameters, such as per-user session. + @provide() + UserManager createManager(@params() Map runtimeParams) { + return UserManager(runtimeParams['id'] as String); + } +} + +// --------------------------------------------------------------------------- +// Example implementations for demonstration only. +// In a real project, these would contain application/service logic. + +/// The main API service. +class ApiService {} + +/// A mock API implementation (for development or testing). +class MockApiService extends ApiService {} + +/// Manages user operations, created using dynamic (runtime) parameters. +class UserManager { + final String id; + UserManager(this.id); +} + +/// Global logger service. +class Logger {} + +void main() { + // After running code generation, injectors and mixins will be ready to use. + // Example integration (pseudo-code): + // + // import 'package:cherrypick/cherrypick.dart'; + // + // final scope = CherryPick.openRootScope()..installModules([$AppModule()]); + // final screen = ApiScreen()..injectFields(); + // print(screen.apiService); // <-- injected! + // + // This main() is provided for reference only. +} diff --git a/cherrypick_annotations/lib/cherrypick_annotations.dart b/cherrypick_annotations/lib/cherrypick_annotations.dart index dd4c01e..5d09724 100644 --- a/cherrypick_annotations/lib/cherrypick_annotations.dart +++ b/cherrypick_annotations/lib/cherrypick_annotations.dart @@ -1,5 +1,3 @@ -library; - // // Copyright 2021 Sergey Penkovsky (sergey.penkovsky@gmail.com) // Licensed under the Apache License, Version 2.0 (the "License"); @@ -13,6 +11,24 @@ library; // limitations under the License. // +/// Annotations for use with the CherryPick dependency injection generator. +/// +/// These annotations are used on classes, methods, fields or parameters to +/// describe how they should participate in dependency injection. +/// See: https://pub.dev/packages/cherrypick +/// +/// Example: +/// ```dart +/// import 'package:cherrypick_annotations/cherrypick_annotations.dart'; +/// +/// @injectable() +/// class MyService { +/// @inject() +/// late final Logger logger; +/// } +/// ``` +library; + export 'src/module.dart'; export 'src/provide.dart'; export 'src/instance.dart'; diff --git a/cherrypick_annotations/lib/src/inject.dart b/cherrypick_annotations/lib/src/inject.dart index 02eedcc..5435c59 100644 --- a/cherrypick_annotations/lib/src/inject.dart +++ b/cherrypick_annotations/lib/src/inject.dart @@ -38,5 +38,6 @@ import 'package:meta/meta.dart'; /// ``` @experimental final class inject { + /// Creates an [inject] annotation for field injection. const inject(); } diff --git a/cherrypick_annotations/lib/src/injectable.dart b/cherrypick_annotations/lib/src/injectable.dart index 8ce1336..7c97249 100644 --- a/cherrypick_annotations/lib/src/injectable.dart +++ b/cherrypick_annotations/lib/src/injectable.dart @@ -39,5 +39,6 @@ import 'package:meta/meta.dart'; /// After running the generator, the mixin (`_\$ProfileScreen`) will be available to help auto-inject all [@inject] fields in your widget/service/controller. @experimental final class injectable { + /// Creates an [injectable] annotation for classes. const injectable(); } diff --git a/cherrypick_annotations/lib/src/instance.dart b/cherrypick_annotations/lib/src/instance.dart index 6e32e65..de8b500 100644 --- a/cherrypick_annotations/lib/src/instance.dart +++ b/cherrypick_annotations/lib/src/instance.dart @@ -45,5 +45,6 @@ import 'package:meta/meta.dart'; /// See also: [@singleton] @experimental final class instance { + /// Creates an [instance] annotation for classes or providers. const instance(); } diff --git a/cherrypick_annotations/lib/src/provide.dart b/cherrypick_annotations/lib/src/provide.dart index 0f42043..402f207 100644 --- a/cherrypick_annotations/lib/src/provide.dart +++ b/cherrypick_annotations/lib/src/provide.dart @@ -39,6 +39,6 @@ import 'package:meta/meta.dart'; /// See also: [@singleton], [@instance], [@params], [@named] @experimental final class provide { - /// Creates a [provide] annotation. + /// Creates a [provide] annotation for marking provider methods/classes in DI modules. const provide(); } diff --git a/cherrypick_annotations/lib/src/scope.dart b/cherrypick_annotations/lib/src/scope.dart index ecfc054..a883095 100644 --- a/cherrypick_annotations/lib/src/scope.dart +++ b/cherrypick_annotations/lib/src/scope.dart @@ -49,5 +49,7 @@ import 'package:meta/meta.dart'; final class scope { /// The name/key of the DI scope from which to resolve this dependency. final String? name; + + /// Creates a [scope] annotation specifying which DI scope to use for the dependency resolution. const scope(this.name); }