From 4f5e72e745b449a45100ea9160d3ca80bde2d182 Mon Sep 17 00:00:00 2001 From: Francesco Vallone Date: Tue, 10 Sep 2024 12:26:10 +0200 Subject: [PATCH 1/2] feat(#67): add the Provider.deferred shorthand --- .website/core/controllers.md | 2 +- .website/core/providers.md | 8 +++++++- packages/serinus/lib/src/core/provider.dart | 11 +++++++++++ packages/serinus/test/core/provider_test.dart | 9 +++++++++ 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/.website/core/controllers.md b/.website/core/controllers.md index 7e0400d3..efcbf585 100644 --- a/.website/core/controllers.md +++ b/.website/core/controllers.md @@ -52,4 +52,4 @@ class MyController extends Controller { } ``` -You can find more information about metadata in the [Metadata](/core/metadata.html) section. \ No newline at end of file +You can find more information about metadata in the [Metadata](/core/metadata.html) section. diff --git a/.website/core/providers.md b/.website/core/providers.md index 522ef026..eb5657a1 100644 --- a/.website/core/providers.md +++ b/.website/core/providers.md @@ -87,6 +87,7 @@ class MyModule extends Module { ) } ``` + ::: ## Global Providers @@ -103,13 +104,18 @@ class MyProvider extends Provider { ## Deferred Providers -By default, all providers are created when the module is created. If you want to create the provider after all the modules are created, you can extend the `DeferredProvider` class. +By default, all providers are created when the module is created. If you want to create the provider after all the modules are registered, you can extend the `DeferredProvider` class. This class has a `init` property that accepts a function that returns the provider. Also the `init` function has access to the application context and contains all the providers initialized. When a DeferredProvider is initialized, its provider is added to the application context so that it can be used as dependency by other providers. This grant a incremental initialization of the providers. +::: tip +You can also use a shorthand to create a DeferredProvider by using the `Provider.deferred` factory constructor. +This constructor uses the same parameters as the `DeferredProvider` class. +::: + ::: code-group ```dart [Deferred Provider] diff --git a/packages/serinus/lib/src/core/provider.dart b/packages/serinus/lib/src/core/provider.dart index 0e09eb4b..64d56c8c 100644 --- a/packages/serinus/lib/src/core/provider.dart +++ b/packages/serinus/lib/src/core/provider.dart @@ -7,6 +7,17 @@ abstract class Provider { /// The [Provider] constructor is used to create a new instance of the [Provider] class. const Provider({this.isGlobal = false}); + + /// The factory constructor [Provider.deferred] is used to create a new instance of the [Provider] class with dependencies. + /// It uses the [DeferredProvider] class to define a provider that is initialized asynchronously. + /// + /// The [init] function is called when the provider is initialized. + /// The [inject] property contains the types of other [Provider]s that will be injected in the provider. + factory Provider.deferred( + Future Function(ApplicationContext context) init, { + required List inject, + }) => DeferredProvider(init, inject: inject); + } /// The [DeferredProvider] class is used to define a provider that is initialized asynchronously. diff --git a/packages/serinus/test/core/provider_test.dart b/packages/serinus/test/core/provider_test.dart index f6ab4bc9..ec98114b 100644 --- a/packages/serinus/test/core/provider_test.dart +++ b/packages/serinus/test/core/provider_test.dart @@ -13,6 +13,10 @@ class TestProviderDependent extends Provider { TestProviderDependent(TestProvider provider); } +class TestProviderDependent2 extends Provider { + TestProviderDependent2(TestProvider provider); +} + class TestProviderOnInit extends Provider with OnApplicationInit { bool isInitialized = false; @@ -100,6 +104,10 @@ void main() async { DeferredProvider((context) async { final dep = context.use(); return TestProviderDependent(dep); + }, inject: [TestProvider]), + Provider.deferred((context) async { + final dep = context.use(); + return TestProviderDependent2(dep); }, inject: [TestProvider]) ]); await container.registerModules(module, Type); @@ -107,6 +115,7 @@ void main() async { await container.finalize(module); expect(container.get(), isNotNull); + expect(container.get(), isNotNull); }); test( From 1b544fce9aaafa8421ca7cc3ecbd055e006159c4 Mon Sep 17 00:00:00 2001 From: Francesco Vallone Date: Tue, 10 Sep 2024 12:28:35 +0200 Subject: [PATCH 2/2] feat(#67): format files --- packages/serinus/bin/serinus.dart | 9 ++++++--- packages/serinus/lib/src/adapters/http_adapter.dart | 6 +++--- .../serinus/lib/src/containers/module_container.dart | 6 ++++-- packages/serinus/lib/src/core/provider.dart | 6 +++--- .../serinus/lib/src/extensions/iterable_extansions.dart | 2 +- packages/serinus/lib/src/handlers/handler.dart | 5 +---- packages/serinus/lib/src/handlers/request_handler.dart | 2 +- 7 files changed, 19 insertions(+), 17 deletions(-) diff --git a/packages/serinus/bin/serinus.dart b/packages/serinus/bin/serinus.dart index f8e10840..7cbbb629 100644 --- a/packages/serinus/bin/serinus.dart +++ b/packages/serinus/bin/serinus.dart @@ -117,9 +117,12 @@ class PostRoute extends Route { class HomeController extends Controller { HomeController({super.path = '/'}) { - on(GetRoute(path: '/'), (context) async { - return 'Hello world'; - },); + on( + GetRoute(path: '/'), + (context) async { + return 'Hello world'; + }, + ); on(PostRoute(path: '/*'), (context) async { return '${context.request.getData('test')} ${context.params}'; }, diff --git a/packages/serinus/lib/src/adapters/http_adapter.dart b/packages/serinus/lib/src/adapters/http_adapter.dart index 0d1da83d..945d32f5 100644 --- a/packages/serinus/lib/src/adapters/http_adapter.dart +++ b/packages/serinus/lib/src/adapters/http_adapter.dart @@ -4,11 +4,11 @@ import '../http/internal_request.dart'; import 'server_adapter.dart'; /// The [HttpAdapter] class is used to create an HTTP server adapter. -/// +/// /// It extends the [Adapter] class and allows the developer to define the host, port, and powered by header. -/// +/// /// The class must be extended and the [init], [close], and [listen] methods must be implemented. -/// +/// /// Properties: /// - [host]: The host of the server. /// - [port]: The port of the server. diff --git a/packages/serinus/lib/src/containers/module_container.dart b/packages/serinus/lib/src/containers/module_container.dart index b4b71731..27d730da 100644 --- a/packages/serinus/lib/src/containers/module_container.dart +++ b/packages/serinus/lib/src/containers/module_container.dart @@ -63,14 +63,16 @@ final class ModulesContainer { Future registerModule(Module module, Type entrypoint, [ModuleInjectables? moduleInjectables]) async { final token = moduleToken(module); - final initializedModule = _modules[token] = await module.registerAsync(config); + final initializedModule = + _modules[token] = await module.registerAsync(config); if (initializedModule.runtimeType == entrypoint && initializedModule.exports.isNotEmpty) { throw InitializationError('The entrypoint module cannot have exports'); } _providers[token] = []; if (_moduleInjectables.containsKey(token)) { - _moduleInjectables[token] = moduleInjectables!.concatTo(_moduleInjectables[token]); + _moduleInjectables[token] = + moduleInjectables!.concatTo(_moduleInjectables[token]); } else { final newInjectables = ModuleInjectables( middlewares: {...module.middlewares}, diff --git a/packages/serinus/lib/src/core/provider.dart b/packages/serinus/lib/src/core/provider.dart index 64d56c8c..327b2c5b 100644 --- a/packages/serinus/lib/src/core/provider.dart +++ b/packages/serinus/lib/src/core/provider.dart @@ -10,14 +10,14 @@ abstract class Provider { /// The factory constructor [Provider.deferred] is used to create a new instance of the [Provider] class with dependencies. /// It uses the [DeferredProvider] class to define a provider that is initialized asynchronously. - /// + /// /// The [init] function is called when the provider is initialized. /// The [inject] property contains the types of other [Provider]s that will be injected in the provider. factory Provider.deferred( Future Function(ApplicationContext context) init, { required List inject, - }) => DeferredProvider(init, inject: inject); - + }) => + DeferredProvider(init, inject: inject); } /// The [DeferredProvider] class is used to define a provider that is initialized asynchronously. diff --git a/packages/serinus/lib/src/extensions/iterable_extansions.dart b/packages/serinus/lib/src/extensions/iterable_extansions.dart index 9535d47e..b9c20b9b 100644 --- a/packages/serinus/lib/src/extensions/iterable_extansions.dart +++ b/packages/serinus/lib/src/extensions/iterable_extansions.dart @@ -19,7 +19,7 @@ extension AddIfAbsent on Iterable { Iterable addAllIfAbsent(Iterable elements) { final elementsType = map((e) => e.runtimeType); final currentElements = [...this]; - for(final element in elements) { + for (final element in elements) { if (!elementsType.contains(element.runtimeType)) { currentElements.add(element); } diff --git a/packages/serinus/lib/src/handlers/handler.dart b/packages/serinus/lib/src/handlers/handler.dart index fda3e5c4..ebc3a90a 100644 --- a/packages/serinus/lib/src/handlers/handler.dart +++ b/packages/serinus/lib/src/handlers/handler.dart @@ -52,10 +52,7 @@ abstract class Handler { RequestContext buildRequestContext(Iterable providers, Request request, InternalResponse response) { return RequestContext( - { - for (final provider in providers) - provider.runtimeType: provider - }, + {for (final provider in providers) provider.runtimeType: provider}, request, StreamableResponse(response), ); diff --git a/packages/serinus/lib/src/handlers/request_handler.dart b/packages/serinus/lib/src/handlers/request_handler.dart index 7a0c2d1c..17fa0ea0 100644 --- a/packages/serinus/lib/src/handlers/request_handler.dart +++ b/packages/serinus/lib/src/handlers/request_handler.dart @@ -50,7 +50,7 @@ class RequestHandler extends Handler { : request.path, request.method.toHttpMethod()); final routeData = routeLookup.route; - if(routeLookup.params.isNotEmpty) { + if (routeLookup.params.isNotEmpty) { wrappedRequest.params = routeLookup.params; } if (routeData == null) {