refactor(zero): beginning feature branch

This commit is contained in:
Patrick Stewart 2024-11-25 20:35:42 -07:00
parent f2f81f11df
commit c2a864ab38
675 changed files with 651 additions and 61127 deletions

View file

@ -1,9 +0,0 @@
library angel3_bus;
export 'src/dispatcher.dart';
export 'src/command.dart';
export 'src/handler.dart';
export 'src/queue.dart';
export 'src/batch.dart';
export 'src/chain.dart';
export 'src/bus_service_provider.dart';

View file

@ -1,19 +0,0 @@
import 'command.dart';
import 'dispatcher.dart';
class Batch {
// Implement Batch
}
class PendingBatch {
final Dispatcher _dispatcher;
final List<Command> _commands;
PendingBatch(this._dispatcher, this._commands);
Future<void> dispatch() async {
for (var command in _commands) {
await _dispatcher.dispatch(command);
}
}
}

View file

@ -1,60 +0,0 @@
// // lib/src/bus_service_provider.dart
// import 'package:angel3_framework/angel3_framework.dart';
// import 'package:angel3_event_bus/angel3_event_bus.dart';
// import 'package:angel3_mq/angel3_mq.dart';
// import 'dispatcher.dart';
// class BusServiceProvider extends Provider {
// @override
// Future<void> boot(Angel app) async {
// // Register EventBus
// app.container.registerSingleton<EventBus>(EventBus());
// // Register Queue
// app.container.registerSingleton<Queue>(MemoryQueue());
// // Create and register the Dispatcher
// final dispatcher = Dispatcher(app.container);
// app.container.registerSingleton<Dispatcher>(dispatcher);
// // Register any global middleware or mappings
// dispatcher.pipeThrough([
// // Add any global middleware here
// ]);
// // Register command-to-handler mappings
// dispatcher.map({
// // Add your command-to-handler mappings here
// // Example: ExampleCommand: ExampleCommandHandler,
// });
// }
// }
// class MemoryQueue implements Queue {
// final List<Command> _queue = [];
// @override
// Future<void> push(Command command) async {
// _queue.add(command);
// }
// @override
// Future<void> later(Duration delay, Command command) async {
// await Future.delayed(delay);
// _queue.add(command);
// }
// @override
// Future<void> pushOn(String queue, Command command) async {
// // For simplicity, ignoring the queue parameter in this implementation
// _queue.add(command);
// }
// @override
// Future<void> laterOn(String queue, Duration delay, Command command) async {
// // For simplicity, ignoring the queue parameter in this implementation
// await Future.delayed(delay);
// _queue.add(command);
// }
// }

View file

@ -1,15 +0,0 @@
import 'command.dart';
import 'dispatcher.dart';
class PendingChain {
final Dispatcher _dispatcher;
final List<Command> _commands;
PendingChain(this._dispatcher, this._commands);
Future<void> dispatch() async {
for (var command in _commands) {
await _dispatcher.dispatch(command);
}
}
}

View file

@ -1,5 +0,0 @@
// lib/src/command.dart
abstract class Command {}
abstract class ShouldQueue implements Command {}

View file

@ -1,251 +0,0 @@
// lib/src/dispatcher.dart
import 'dart:async';
import 'package:platform_container/container.dart';
import 'package:angel3_reactivex/angel3_reactivex.dart';
import 'package:angel3_event_bus/event_bus.dart';
import 'package:angel3_mq/mq.dart';
import 'command.dart';
import 'handler.dart';
import 'batch.dart';
import 'chain.dart';
/// A class that handles dispatching and processing of commands.
///
/// This dispatcher supports both synchronous and asynchronous command execution,
/// as well as queueing commands for later processing.
class Dispatcher implements QueueingDispatcher {
final Container container;
final EventBus _eventBus;
final Subject<Command> _commandSubject;
final MQClient _queue;
final Map<Type, Type> _handlers = {};
/// Creates a new [Dispatcher] instance.
///
/// [container] is used for dependency injection and to retrieve necessary services.
Dispatcher(this.container)
: _eventBus = container.make<EventBus>(),
_commandSubject = BehaviorSubject<Command>(),
_queue = container.make<MQClient>() {
_setupCommandProcessing();
}
/// Sets up the command processing pipeline.
///
/// This method initializes the stream that processes commands and emits events.
void _setupCommandProcessing() {
_commandSubject
.flatMap((command) => Stream.fromFuture(_processCommand(command))
.map((result) => CommandEvent(command, result: result))
.onErrorReturnWith(
(error, stackTrace) => CommandEvent(command, error: error)))
.listen((event) {
_eventBus.fire(event);
});
}
/// Dispatches a command for execution.
///
/// If the command implements [ShouldQueue], it will be dispatched to a queue.
/// Otherwise, it will be executed immediately.
///
/// [command] is the command to be dispatched.
@override
Future<dynamic> dispatch(Command command) {
if (command is ShouldQueue) {
return dispatchToQueue(command);
} else {
return dispatchNow(command);
}
}
/// Dispatches a command for immediate execution.
///
/// [command] is the command to be executed.
/// [handler] is an optional specific handler for the command.
@override
Future<dynamic> dispatchNow(Command command, [Handler? handler]) {
final completer = Completer<dynamic>();
_commandSubject.add(command);
_eventBus
.on<CommandEvent>()
.where((event) => event.command == command)
.take(1)
.listen((event) {
if (event.error != null) {
completer.completeError(event.error);
} else {
completer.complete(event.result);
}
});
return completer.future;
}
/// Processes a command by finding and executing its appropriate handler.
///
/// [command] is the command to be processed.
Future<dynamic> _processCommand(Command command) async {
final handlerType = _handlers[command.runtimeType];
if (handlerType != null) {
final handler = container.make(handlerType) as Handler;
return await handler.handle(command);
} else {
throw Exception('No handler found for command: ${command.runtimeType}');
}
}
/// Dispatches a command to a queue for later processing.
///
/// [command] is the command to be queued.
@override
Future<dynamic> dispatchToQueue(Command command) async {
final message = Message(
payload: command,
headers: {
'commandType': command.runtimeType.toString(),
},
);
_queue.sendMessage(
message: message,
// You might want to specify an exchange name and routing key if needed
// exchangeName: 'your_exchange_name',
// routingKey: 'your_routing_key',
);
return message.id;
}
/// Dispatches a command synchronously.
///
/// This is an alias for [dispatchNow].
///
/// [command] is the command to be executed.
/// [handler] is an optional specific handler for the command.
@override
Future<dynamic> dispatchSync(Command command, [Handler? handler]) {
return dispatchNow(command, handler);
}
/// Finds a batch by its ID.
///
/// [batchId] is the ID of the batch to find.
@override
Future<Batch?> findBatch(String batchId) async {
// Implement batch finding logic
throw UnimplementedError();
}
/// Creates a new pending batch of commands.
///
/// [commands] is the list of commands to be included in the batch.
@override
PendingBatch batch(List<Command> commands) {
return PendingBatch(this, commands);
}
/// Creates a new pending chain of commands.
///
/// [commands] is the list of commands to be included in the chain.
@override
PendingChain chain(List<Command> commands) {
return PendingChain(this, commands);
}
/// Applies a list of pipes to the command processing pipeline.
///
/// [pipes] is the list of pipes to be applied.
@override
Dispatcher pipeThrough(List<Pipe> pipes) {
_commandSubject.transform(
StreamTransformer.fromHandlers(
handleData: (data, sink) {
var result = data;
for (var pipe in pipes) {
result = pipe(result);
}
sink.add(result);
},
),
);
return this;
}
/// Maps command types to their respective handler types.
///
/// [handlers] is a map where keys are command types and values are handler types.
@override
Dispatcher map(Map<Type, Type> handlers) {
_handlers.addAll(handlers);
return this;
}
/// Dispatches a command to be executed after the current request-response cycle.
///
/// [command] is the command to be dispatched after the response.
@override
void dispatchAfterResponse(Command command) {
final message = Message(
payload: command,
headers: {
'commandType': command.runtimeType.toString(),
'dispatchAfterResponse': 'true',
},
);
_queue.sendMessage(
message: message,
// You might want to specify an exchange name if needed
// exchangeName: 'your_exchange_name',
// If you want to use a specific queue for after-response commands:
routingKey: 'after_response_queue',
);
}
}
abstract class QueueingDispatcher {
Future<dynamic> dispatch(Command command);
Future<dynamic> dispatchSync(Command command, [Handler? handler]);
Future<dynamic> dispatchNow(Command command, [Handler? handler]);
Future<dynamic> dispatchToQueue(Command command);
Future<Batch?> findBatch(String batchId);
PendingBatch batch(List<Command> commands);
PendingChain chain(List<Command> commands);
Dispatcher pipeThrough(List<Pipe> pipes);
Dispatcher map(Map<Type, Type> handlers);
void dispatchAfterResponse(Command command);
}
typedef Pipe = Command Function(Command);
class CommandCompletedEvent extends AppEvent {
final dynamic result;
CommandCompletedEvent(this.result);
@override
List<Object?> get props => [result];
}
class CommandErrorEvent extends AppEvent {
final dynamic error;
CommandErrorEvent(this.error);
@override
List<Object?> get props => [error];
}
class CommandEvent extends AppEvent {
final Command command;
final dynamic result;
final dynamic error;
CommandEvent(this.command, {this.result, this.error});
@override
List<Object?> get props => [command, result, error];
}

View file

@ -1,5 +0,0 @@
import 'command.dart';
abstract class Handler {
Future<dynamic> handle(Command command);
}

View file

@ -1,8 +0,0 @@
import 'command.dart';
abstract class Queue {
Future<void> push(Command command);
Future<void> later(Duration delay, Command command);
Future<void> pushOn(String queue, Command command);
Future<void> laterOn(String queue, Duration delay, Command command);
}

View file

@ -1,197 +0,0 @@
import 'dart:async';
import 'package:platform_bus/angel3_bus.dart';
import 'package:platform_container/container.dart';
import 'package:angel3_event_bus/event_bus.dart';
import 'package:angel3_mq/mq.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
class IsMessage extends Matcher {
@override
bool matches(item, Map matchState) => item is Message;
@override
Description describe(Description description) =>
description.add('is a Message');
}
class MockContainer extends Mock implements Container {
final Map<Type, dynamic> _instances = {};
@override
T make<T>([Type? type]) {
type ??= T;
return _instances[type] as T;
}
void registerInstance<T>(T instance) {
_instances[T] = instance;
}
}
class MockEventBus extends Mock implements EventBus {
@override
Stream<T> on<T extends AppEvent>() {
return super.noSuchMethod(
Invocation.method(#on, [], {#T: T}),
returnValue: Stream<T>.empty(),
) as Stream<T>;
}
}
class MockMQClient extends Mock implements MQClient {
Message? capturedMessage;
String? capturedExchangeName;
String? capturedRoutingKey;
@override
dynamic noSuchMethod(Invocation invocation,
{Object? returnValue, Object? returnValueForMissingStub}) {
if (invocation.memberName == #sendMessage) {
final namedArgs = invocation.namedArguments;
capturedMessage = namedArgs[#message] as Message?;
capturedExchangeName = namedArgs[#exchangeName] as String?;
capturedRoutingKey = namedArgs[#routingKey] as String?;
return null;
}
return super.noSuchMethod(invocation,
returnValue: returnValue,
returnValueForMissingStub: returnValueForMissingStub);
}
}
class TestCommand implements Command {
final String data;
TestCommand(this.data);
}
class TestHandler implements Handler {
@override
Future<dynamic> handle(Command command) async {
if (command is TestCommand) {
return 'Handled: ${command.data}';
}
throw UnimplementedError();
}
}
class TestQueuedCommand implements Command, ShouldQueue {
final String data;
TestQueuedCommand(this.data);
}
void main() {
late MockContainer container;
late MockEventBus eventBus;
late MockMQClient mqClient;
late Dispatcher dispatcher;
setUp(() {
container = MockContainer();
eventBus = MockEventBus();
mqClient = MockMQClient();
container.registerInstance<EventBus>(eventBus);
container.registerInstance<MQClient>(mqClient);
dispatcher = Dispatcher(container);
});
group('Dispatcher', () {
test('dispatchNow should handle command and return result', () async {
final command = TestCommand('test data');
final handler = TestHandler();
container.registerInstance<TestHandler>(handler);
dispatcher.map({TestCommand: TestHandler});
final commandEventController = StreamController<CommandEvent>();
when(eventBus.on<CommandEvent>())
.thenAnswer((_) => commandEventController.stream);
final future = dispatcher.dispatchNow(command);
// Simulate the event firing
commandEventController
.add(CommandEvent(command, result: 'Handled: test data'));
final result = await future;
expect(result, equals('Handled: test data'));
await commandEventController.close();
});
test('dispatch should handle regular commands immediately', () async {
final command = TestCommand('regular');
final handler = TestHandler();
container.registerInstance<TestHandler>(handler);
dispatcher.map({TestCommand: TestHandler});
final commandEventController = StreamController<CommandEvent>();
when(eventBus.on<CommandEvent>())
.thenAnswer((_) => commandEventController.stream);
final future = dispatcher.dispatch(command);
// Simulate the event firing
commandEventController
.add(CommandEvent(command, result: 'Handled: regular'));
final result = await future;
expect(result, equals('Handled: regular'));
await commandEventController.close();
});
test('dispatch should queue ShouldQueue commands', () async {
final command = TestQueuedCommand('queued data');
// Dispatch the command
await dispatcher.dispatch(command);
// Verify that sendMessage was called and check the message properties
expect(mqClient.capturedMessage, isNotNull);
expect(mqClient.capturedMessage!.payload, equals(command));
expect(mqClient.capturedMessage!.headers?['commandType'],
equals('TestQueuedCommand'));
// Optionally, verify exchange name and routing key if needed
expect(mqClient.capturedExchangeName, isNull);
expect(mqClient.capturedRoutingKey, isNull);
});
test(
'dispatchAfterResponse should send message to queue with specific header',
() {
final command = TestCommand('after response data');
// Call dispatchAfterResponse
dispatcher.dispatchAfterResponse(command);
// Verify that sendMessage was called and check the message properties
expect(mqClient.capturedMessage, isNotNull);
expect(mqClient.capturedMessage!.payload, equals(command));
expect(mqClient.capturedMessage!.headers?['commandType'],
equals('TestCommand'));
expect(mqClient.capturedMessage!.headers?['dispatchAfterResponse'],
equals('true'));
// Verify routing key
expect(mqClient.capturedRoutingKey, equals('after_response_queue'));
// Optionally, verify exchange name if needed
expect(mqClient.capturedExchangeName, isNull);
});
test('map should register command handlers', () {
dispatcher.map({TestCommand: TestHandler});
// Mock the event bus behavior for this test
when(eventBus.on<CommandEvent>()).thenAnswer((_) => Stream.empty());
// This test is a bit tricky to verify directly, but we can check if dispatch doesn't throw
expect(() => dispatcher.dispatch(TestCommand('test')), returnsNormally);
});
});
}

View file

View file

View file

View file

@ -1,18 +1,16 @@
name: platform_pipeline
description: The Pipeline Package for the Protevus Platform
name: platform_config
description: The Configuration Package for the Protevus Platform
version: 0.0.1
homepage: https://protevus.com
documentation: https://docs.protevus.com
repository: https://github.com/protevus/platform
repository: https://git.protevus.com/protevus/platform
environment:
sdk: ^3.4.2
# Add regular dependencies here.
dependencies:
platform_container: ^9.0.0
platform_core: ^9.0.0
logging: ^1.1.0
#protevus_runtime: ^0.0.1
dev_dependencies:
lints: ^3.0.0

View file

View file

@ -1,71 +0,0 @@
# See https://www.dartlang.org/tools/private-files.html
# Files and directories created by pub
.dart_tool
.packages
.pub/
build/
# If you're building an application, you may want to check-in your pubspec.lock
pubspec.lock
# Directory created by dartdoc
# If you don't generate documentation locally you can remove this line.
doc/api/
### Dart template
# See https://www.dartlang.org/tools/private-files.html
# Files and directories created by pub
# SDK 1.20 and later (no longer creates packages directories)
# Older SDK versions
# (Include if the minimum SDK version specified in pubsepc.yaml is earlier than 1.20)
.project
.buildlog
**/packages/
# Files created by dart2js
# (Most Dart developers will use pub build to compile Dart, use/modify these
# rules if you intend to use dart2js directly
# Convention is to use extension '.dart.js' for Dart compiled to Javascript to
# differentiate from explicit Javascript files)
*.dart.js
*.part.js
*.js.deps
*.js.map
*.info.json
# Directory created by dartdoc
# Don't commit pubspec lock file
# (Library packages only! Remove pattern if developing an application package)
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
## VsCode
.vscode/
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
.idea/
/out/
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

View file

@ -1,12 +0,0 @@
Primary Authors
===============
* __[Thomas Hii](dukefirehawk.apps@gmail.com)__
Thomas is the current maintainer of the code base. He has refactored and migrated the
code base to support NNBD.
* __[Tobe O](thosakwe@gmail.com)__
Tobe has written much of the original code prior to NNBD migration. He has moved on and
is no longer involved with the project.

View file

@ -1,151 +0,0 @@
# Change Log
## 8.1.1
* Updated repository link
## 8.1.0
* Updated `lints` to 3.0.0
* Fixed analyser warnings
## 8.0.0
* Require Dart >= 3.0
## 7.1.0-beta.2
* Require Dart >= 2.19
* Refactored `EmptyReflector`
## 7.1.0-beta.1
* Require Dart >= 2.18
* Moved `defaultErrorMessage` to `ContainerConst` class to resolve reflectatable issue.
* Added `hashCode`
## 7.0.0
* Require Dart >= 2.17
## 6.0.0
* Require Dart >= 2.16
* Removed `error`
## 5.0.0
* Skipped release
## 4.0.0
* Skipped release
## 3.1.1
* Updated `_ReflectedMethodMirror` to have optional `returnType` parameter
* Updated `Container` to handle non nullable type
## 3.1.0
* Updated linter to `package:lints`
## 3.0.2
* Resolved static analysis warnings
## 3.0.1
* Updated README
## 3.0.0
* Migrated to support Dart >= 2.12 NNBD
## 2.0.0
* Migrated to work with Dart >= 2.12 Non NNBD
## 1.1.0
* `pedantic` lints.
* Add `ThrowingReflector`, which throws on all operations.
* `EmptyReflector` uses `Object` instead of `dynamic` as its returned
type, as the `dynamic` type is (apparently?) no longer a valid constant value.
* `registerSingleton` now returns the provided `object`.
* `registerFactory` and `registerLazySingleton` now return the provided function `f`.
## 1.0.4
* Slight patch to prevent annoying segfault.
## 1.0.3
* Added `Future` support to `Reflector`.
## 1.0.2
* Added `makeAsync<T>`.
## 1.0.1
* Added `hasNamed`.
## 1.0.0
* Removed `@GenerateReflector`.
## 1.0.0-alpha.12
* `StaticReflector` now defaults to empty arguments.
## 1.0.0-alpha.11
* Added `StaticReflector`.
## 1.0.0-alpha.10
* Added `Container.registerLazySingleton<T>`.
* Added named singleton support.
## 1.0.0-alpha.9
* Added `Container.has<T>`.
## 1.0.0-alpha.8
* Fixed a bug where `_ReflectedTypeInstance.isAssignableTo` always failed.
* Added `@GenerateReflector` annotation.
## 1.0.0-alpha.7
* Add `EmptyReflector`.
* `ReflectedType.newInstance` now returns a `ReflectedInstance`.
* Moved `ReflectedInstance.invoke` to `ReflectedFunction.invoke`.
## 1.0.0-alpha.6
* Add `getField` to `ReflectedInstance`.
## 1.0.0-alpha.5
* Remove concrete type from `ReflectedTypeParameter`.
## 1.0.0-alpha.4
* Safely handle `void` return types of methods.
## 1.0.0-alpha.3
* Reflecting `void` in `MirrorsReflector` now forwards to `dynamic`.
## 1.0.0-alpha.2
* Added `ReflectedInstance.reflectee`.
## 1.0.0-alpha.1
* Allow omission of the first argument of `Container.make`, to use
a generic type argument instead.
* `singleton` -> `registerSingleton`
* Add `createChild`, and support hierarchical containers.

View file

@ -1,29 +0,0 @@
BSD 3-Clause License
Copyright (c) 2021, dukefirehawk.com
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,45 +0,0 @@
# Protevus Container
![Pub Version (including pre-releases)](https://img.shields.io/pub/v/platform_container?include_prereleases)
[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)
[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion)
[![License](https://img.shields.io/github/license/dart-backend/angel)](https://github.com/dart-backend/angel/tree/master/packages/container/angel_container/LICENSE)
A better IoC container for Protevus, ultimately allowing Protevus to be used with or without `dart:mirrors` package.
```dart
import 'package:platform_container/mirrors.dart';
import 'package:platform_core/core.dart';
import 'package:platform_core/http.dart';
@Expose('/sales', middleware: [process1])
class SalesController extends Controller {
@Expose('/', middleware: [process2])
Future<String> route1(RequestContext req, ResponseContext res) async {
return "Sales route";
}
}
bool process1(RequestContext req, ResponseContext res) {
res.write('Hello, ');
return true;
}
bool process2(RequestContext req, ResponseContext res) {
res.write('From Sales, ');
return true;
}
void main() async {
// Using Mirror Reflector
var app = Protevus(reflector: MirrorsReflector());
// Sales Controller
app.container.registerSingleton<SalesController>(SalesController());
await app.mountController<SalesController>();
var http = PlatformHttp(app);
var server = await http.startServer('localhost', 3000);
print("Protevus server listening at ${http.uri}");
}
```

View file

@ -1 +0,0 @@
include: package:lints/recommended.yaml

View file

@ -1,75 +0,0 @@
import 'dart:async';
import 'package:platform_container/container.dart';
import 'package:platform_container/mirrors.dart';
Future<void> main() async {
// Create a container instance.
var container = Container(const MirrorsReflector());
// Register a singleton.
container.registerSingleton<Engine>(Engine(40));
// You can also omit the type annotation, in which the object's runtime type will be used.
// If you're injecting an abstract class, prefer the type annotation.
//
// container.registerSingleton(Engine(40));
// Register a factory that creates a truck.
container.registerFactory<Truck>((container) {
return _TruckImpl(container.make<Engine>());
});
// Use `make` to create an instance.
var truck = container.make<Truck>();
// You can also resolve injections asynchronously.
container.registerFactory<Future<int>>((_) async => 24);
print(await container.makeAsync<int>());
// Asynchronous resolution also works for plain objects.
await container.makeAsync<Truck>().then((t) => t.drive());
// Register a named singleton.
container.registerNamedSingleton('the_truck', truck);
// Should print: 'Vroom! I have 40 horsepower in my engine.'
truck.drive();
// Should print the same.
container.findByName<Truck>('the_truck').drive();
// We can make a child container with its own factory.
var childContainer = container.createChild();
childContainer.registerFactory<Truck>((container) {
return _TruckImpl(Engine(5666));
});
// Make a truck with 5666 HP.
childContainer.make<Truck>().drive();
// However, calling `make<Engine>` will return the Engine singleton we created above.
print(childContainer.make<Engine>().horsePower);
}
abstract class Truck {
void drive();
}
class Engine {
final int horsePower;
Engine(this.horsePower);
}
class _TruckImpl implements Truck {
final Engine engine;
_TruckImpl(this.engine);
@override
void drive() {
print('Vroom! I have ${engine.horsePower} horsepower in my engine.');
}
}

View file

@ -1,6 +0,0 @@
import 'package:platform_container/container.dart';
void main() {
var reflector = const ThrowingReflector();
reflector.reflectClass(StringBuffer);
}

View file

@ -1,18 +0,0 @@
/*
* This file is part of the Protevus Platform.
*
* (C) Protevus <developers@protevus.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
library platform_container;
export 'src/container.dart';
export 'src/empty/empty.dart';
export 'src/static/static.dart';
export 'src/exception.dart';
export 'src/reflector.dart';
export 'src/throwing.dart';
export 'src/container_const.dart';

View file

@ -1,10 +0,0 @@
/*
* This file is part of the Protevus Platform.
*
* (C) Protevus <developers@protevus.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
export 'src/mirrors/mirrors.dart';

View file

@ -1,396 +0,0 @@
/*
* This file is part of the Protevus Platform.
*
* (C) Protevus <developers@protevus.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import 'dart:async';
import 'exception.dart';
import 'reflector.dart';
class Container {
/// The [Reflector] instance used by this container for reflection-based operations.
///
/// This reflector is used to instantiate objects and resolve dependencies
/// when no explicit factory or singleton is registered for a given type.
final Reflector reflector;
/// A map that stores singleton instances, where the key is the Type and the value is the singleton object.
///
/// This map is used internally by the Container to store and retrieve singleton objects
/// that have been registered using the [registerSingleton] method.
final Map<Type, dynamic> _singletons = {};
/// A map that stores factory functions for creating instances of different types.
///
/// The key is the Type for which the factory is registered, and the value is a function
/// that takes a Container as an argument and returns an instance of that Type.
///
/// This map is used internally by the Container to store and retrieve factory functions
/// that have been registered using the [registerFactory] method.
final Map<Type, dynamic Function(Container)> _factories = {};
/// A map that stores named singleton instances, where the key is a String name and the value is the singleton object.
///
/// This map is used internally by the Container to store and retrieve named singleton objects
/// that have been registered using the [registerNamedSingleton] method. Named singletons allow
/// for multiple instances of the same type to be stored in the container with different names.
final Map<String, dynamic> _namedSingletons = {};
/// The parent container of this container, if any.
///
/// This property is used to create a hierarchy of containers, where child containers
/// can access dependencies registered in their parent containers. If this container
/// is a root container (i.e., it has no parent), this property will be null.
///
/// The parent-child relationship allows for scoped dependency injection, where
/// child containers can override or add to the dependencies defined in their parents.
final Container? _parent;
/// Creates a new root [Container] instance with the given [Reflector].
///
/// This constructor initializes a new container without a parent, making it
/// a root container in the dependency injection hierarchy. The provided
/// [reflector] will be used for all reflection-based operations within this
/// container and its child containers.
///
/// Parameters:
/// - [reflector]: The [Reflector] instance to be used by this container
/// for reflection-based dependency resolution and object instantiation.
///
/// The [_parent] is set to null, indicating that this is a root container.
Container(this.reflector) : _parent = null;
/// Creates a child [Container] instance with the given parent container.
///
/// This constructor is used internally to create child containers in the
/// dependency injection hierarchy. It initializes a new container with a
/// reference to its parent container and uses the same [Reflector] instance
/// as the parent.
///
/// Parameters:
/// - [_parent]: The parent [Container] instance for this child container.
///
/// The [reflector] is initialized with the parent container's reflector,
/// ensuring consistency in reflection operations throughout the container
/// hierarchy.
Container._child(Container this._parent) : reflector = _parent.reflector;
/// Checks if this container is a root container.
///
/// Returns `true` if this container has no parent (i.e., it's a root container),
/// and `false` otherwise.
///
/// This property is useful for determining the position of a container in the
/// dependency injection hierarchy. Root containers are typically used as the
/// top-level containers in an application, while non-root containers are child
/// containers that may have more specific or localized dependencies.
bool get isRoot => _parent == null;
/// Creates a child [Container] that can define its own singletons and factories.
///
/// This method creates a new [Container] instance that is a child of the current container.
/// The child container inherits access to all dependencies registered in its parent containers,
/// but can also define its own singletons and factories that override or extend the parent's dependencies.
///
/// Child containers are useful for creating scoped dependency injection contexts, such as
/// for specific features, modules, or request-scoped dependencies in web applications.
///
/// The child container uses the same [Reflector] instance as its parent.
///
/// Returns:
/// A new [Container] instance that is a child of the current container.
///
/// Example:
/// ```dart
/// var parentContainer = Container(MyReflector());
/// var childContainer = parentContainer.createChild();
/// ```
Container createChild() {
return Container._child(this);
}
/// Determines if the container or any of its parent containers has an injection of the given type.
///
/// This method checks for both singleton and factory registrations of the specified type.
///
/// Parameters:
/// - [T]: The type to check for. If [T] is dynamic, the [t] parameter must be provided.
/// - [t]: An optional Type parameter. If provided, it overrides the type specified by [T].
///
/// Returns:
/// - `true` if an injection (singleton or factory) for the specified type is found in this
/// container or any of its parent containers.
/// - `false` if no injection is found for the specified type in the entire container hierarchy.
///
/// Note:
/// - If [T] is dynamic and [t] is null, the method returns `false` immediately.
/// - The method searches the current container first, then moves up the parent hierarchy
/// until an injection is found or the root container is reached.
bool has<T>([Type? t]) {
var t2 = T;
if (t != null) {
t2 = t;
} else if (T == dynamic && t == null) {
return false;
}
Container? search = this;
while (search != null) {
if (search._singletons.containsKey(t2)) {
return true;
} else if (search._factories.containsKey(t2)) {
return true;
} else {
search = search._parent;
}
}
return false;
}
/// Determines if the container or any of its parent containers has a named singleton with the given [name].
///
/// This method searches the current container and its parent hierarchy for a named singleton
/// registered with the specified [name].
///
/// Parameters:
/// - [name]: The name of the singleton to search for.
///
/// Returns:
/// - `true` if a named singleton with the specified [name] is found in this container
/// or any of its parent containers.
/// - `false` if no named singleton with the specified [name] is found in the entire
/// container hierarchy.
///
/// The method searches the current container first, then moves up the parent hierarchy
/// until a named singleton is found or the root container is reached.
bool hasNamed(String name) {
Container? search = this;
while (search != null) {
if (search._namedSingletons.containsKey(name)) {
return true;
} else {
search = search._parent;
}
}
return false;
}
/// Asynchronously instantiates an instance of [T].
///
/// This method attempts to resolve and return a [Future<T>] in the following order:
/// 1. If an injection of type [T] is registered, it wraps it in a [Future] and returns it.
/// 2. If an injection of type [Future<T>] is registered, it returns it directly.
/// 3. If [T] is [dynamic] and a [Future] of the specified type is registered, it returns that.
/// 4. If none of the above conditions are met, it throws a [ReflectionException].
///
/// Parameters:
/// - [type]: An optional [Type] parameter that can be used to specify the type
/// when [T] is [dynamic] or when a different type than [T] needs to be used.
///
/// Returns:
/// A [Future<T>] representing the asynchronously resolved instance.
///
/// Throws:
/// - [ReflectionException] if no suitable injection is found.
///
/// This method is useful when you need to resolve dependencies that may be
/// registered as either synchronous ([T]) or asynchronous ([Future<T>]) types.
Future<T> makeAsync<T>([Type? type]) {
var t2 = T;
if (type != null) {
t2 = type;
}
Type? futureType; //.Future<T>.value(null).runtimeType;
if (T == dynamic) {
try {
futureType = reflector.reflectFutureOf(t2).reflectedType;
} on UnsupportedError {
// Ignore this.
}
}
if (has<T>(t2)) {
return Future<T>.value(make(t2));
} else if (has<Future<T>>()) {
return make<Future<T>>();
} else if (futureType != null) {
return make(futureType);
} else {
throw ReflectionException(
'No injection for Future<$t2> or $t2 was found.');
}
}
/// Instantiates an instance of [T].
///
/// This method attempts to resolve and return an instance of type [T] in the following order:
/// 1. If a singleton of type [T] is registered in this container or any parent container, it returns that instance.
/// 2. If a factory for type [T] is registered in this container or any parent container, it calls the factory and returns the result.
/// 3. If no singleton or factory is found, it uses reflection to instantiate a new instance of [T].
///
/// For reflection-based instantiation:
/// - It looks for a default constructor or a constructor with an empty name.
/// - It recursively resolves and injects dependencies for the constructor parameters.
/// - It supports both positional and named parameters.
///
/// Parameters:
/// - [type]: An optional [Type] parameter that can be used to specify the type
/// when [T] is [dynamic] or when a different type than [T] needs to be used.
///
/// Returns:
/// An instance of type [T].
///
/// Throws:
/// - [ReflectionException] if [T] is not a class or if it has no default constructor.
/// - Any exception that might occur during the instantiation process.
///
/// This method is central to the dependency injection mechanism, allowing for
/// flexible object creation and dependency resolution within the container hierarchy.
T make<T>([Type? type]) {
Type t2 = T;
if (type != null) {
t2 = type;
}
Container? search = this;
while (search != null) {
if (search._singletons.containsKey(t2)) {
// Find a singleton, if any.
return search._singletons[t2] as T;
} else if (search._factories.containsKey(t2)) {
// Find a factory, if any.
return search._factories[t2]!(this) as T;
} else {
search = search._parent;
}
}
var reflectedType = reflector.reflectType(t2);
var positional = [];
var named = <String, Object>{};
if (reflectedType is ReflectedClass) {
bool isDefault(String name) {
return name.isEmpty || name == reflectedType.name;
}
var constructor = reflectedType.constructors.firstWhere(
(c) => isDefault(c.name),
orElse: (() => throw ReflectionException(
'${reflectedType.name} has no default constructor, and therefore cannot be instantiated.')));
for (var param in constructor.parameters) {
var value = make(param.type.reflectedType);
if (param.isNamed) {
named[param.name] = value;
} else {
positional.add(value);
}
}
return reflectedType.newInstance(
isDefault(constructor.name) ? '' : constructor.name,
positional,
named, []).reflectee as T;
} else {
throw ReflectionException(
'$t2 is not a class, and therefore cannot be instantiated.');
}
}
/// Registers a lazy singleton factory.
///
/// In many cases, you might prefer this to [registerFactory].
///
/// Returns [f].
T Function(Container) registerLazySingleton<T>(T Function(Container) f,
{Type? as}) {
return registerFactory<T>(
(container) {
var r = f(container);
container.registerSingleton<T>(r, as: as);
return r;
},
as: as,
);
}
/// Registers a factory function for creating instances of type [T] in the container.
///
/// Returns [f].
T Function(Container) registerFactory<T>(T Function(Container) f,
{Type? as}) {
Type t2 = T;
if (as != null) {
t2 = as;
}
if (_factories.containsKey(t2)) {
throw StateError('This container already has a factory for $t2.');
}
_factories[t2] = f;
return f;
}
/// Registers a singleton object in the container.
///
/// Returns [object].
T registerSingleton<T>(T object, {Type? as}) {
Type t2 = T;
if (as != null) {
t2 = as;
} else if (T == dynamic) {
t2 = as ?? object.runtimeType;
}
//as ??= T == dynamic ? as : T;
if (_singletons.containsKey(t2)) {
throw StateError('This container already has a singleton for $t2.');
}
_singletons[t2] = object;
return object;
}
/// Retrieves a named singleton from the container or its parent containers.
///
/// In general, prefer using [registerSingleton] and [registerFactory].
///
/// [findByName] is best reserved for internal logic that end users of code should
/// not see.
T findByName<T>(String name) {
if (_namedSingletons.containsKey(name)) {
return _namedSingletons[name] as T;
} else if (_parent != null) {
return _parent.findByName<T>(name);
} else {
throw StateError(
'This container does not have a singleton named "$name".');
}
}
/// Registers a named singleton object in the container.
///
/// Note that this is not related to type-based injections, and exists as a mechanism
/// to enable injecting multiple instances of a type within the same container hierarchy.
T registerNamedSingleton<T>(String name, T object) {
if (_namedSingletons.containsKey(name)) {
throw StateError('This container already has a singleton named "$name".');
}
_namedSingletons[name] = object;
return object;
}
}

View file

@ -1,31 +0,0 @@
/*
* This file is part of the Protevus Platform.
*
* (C) Protevus <developers@protevus.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/// A utility class that contains constant values related to container functionality.
///
/// This class is not meant to be instantiated and only provides static constants.
/// It includes a default error message for reflection-related issues.
class ContainerConst {
/// The default error message for reflection-related issues.
///
/// This message is used when an attempt is made to perform a reflective action,
/// but the `ThrowingReflector` class is being used, which disables reflection.
/// Consider using the `MirrorsReflector` class if reflection is necessary.
static const String defaultErrorMessage =
'You attempted to perform a reflective action, but you are using `ThrowingReflector`, '
'a class which disables reflection. Consider using the `MirrorsReflector` '
'class if you need reflection.';
/// Private constructor to prevent instantiation of this utility class.
///
/// This constructor is marked as private (with the underscore prefix) to ensure
/// that the `ContainerConst` class cannot be instantiated. This is consistent
/// with the class's purpose of only providing static constants.
ContainerConst._();
}

View file

@ -1,377 +0,0 @@
/*
* This file is part of the Protevus Platform.
*
* (C) Protevus <developers@protevus.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import 'package:platform_container/container.dart';
/// A cache to store symbol names.
///
/// This map associates [Symbol] objects with their corresponding string representations.
/// It's used to avoid repeated parsing of symbol names, improving performance
/// when retrieving symbol names multiple times.
final Map<Symbol, String?> _symbolNames = <Symbol, String?>{};
/// A [Reflector] implementation that performs no actual reflection,
/// instead returning empty objects on every invocation.
///
/// Use this in contexts where you know you won't need any reflective capabilities.
///
/// This class provides a lightweight alternative to full reflection when reflection
/// functionality is not required. It returns empty or placeholder objects for all
/// reflection operations, which can be useful in scenarios where reflection is
/// expected but not actually used, or when you want to minimize the overhead of
/// reflection in certain parts of your application.
///
/// The [EmptyReflector] includes:
/// - A static [RegExp] for extracting symbol names without reflection.
/// - Methods to return empty implementations of [ReflectedClass], [ReflectedInstance],
/// [ReflectedType], and [ReflectedFunction].
/// - A [getName] method that uses a cache to store and retrieve symbol names.
///
/// This implementation can be particularly useful in testing scenarios or in
/// production environments where reflection is not needed but the interface
/// expecting reflection capabilities needs to be satisfied.
class EmptyReflector extends Reflector {
/// A [RegExp] that can be used to extract the name of a symbol without reflection.
///
/// This regular expression pattern matches the string representation of a Dart [Symbol],
/// which typically looks like 'Symbol("symbolName")'. It captures the symbol name
/// (the part between the quotes) in a capturing group.
///
/// Usage:
/// ```dart
/// String symbolString = 'Symbol("exampleSymbol")';
/// Match? match = symbolRegex.firstMatch(symbolString);
/// String? symbolName = match?.group(1); // Returns "exampleSymbol"
/// ```
///
/// This is particularly useful in contexts where reflection is not available
/// or desired, allowing for symbol name extraction through string manipulation.
static final RegExp symbolRegex = RegExp(r'Symbol\("([^"]+)"\)');
/// Creates an instance of [EmptyReflector].
///
/// This constructor doesn't take any parameters and creates a lightweight
/// reflector that provides empty implementations for all reflection operations.
/// It's useful in scenarios where reflection capabilities are expected but not
/// actually used, or when you want to minimize the overhead of reflection.
const EmptyReflector();
/// Retrieves the name of a given [Symbol].
///
/// This method attempts to extract the name of the provided [symbol] using
/// the [symbolRegex]. If the name hasn't been cached before, it will be
/// computed and stored in the [_symbolNames] cache for future use.
///
/// The method works as follows:
/// 1. It checks if the symbol's name is already in the cache.
/// 2. If not found, it uses [putIfAbsent] to compute the name:
/// a. It converts the symbol to a string.
/// b. It applies the [symbolRegex] to extract the name.
/// c. If a match is found, it returns the first captured group (the name).
/// 3. The computed name (or null if not found) is stored in the cache and returned.
///
/// @param symbol The [Symbol] whose name is to be retrieved.
/// @return The name of the symbol as a [String], or null if the name couldn't be extracted.
@override
String? getName(Symbol symbol) {
return _symbolNames.putIfAbsent(
symbol, () => symbolRegex.firstMatch(symbol.toString())?.group(1));
}
/// Returns an empty [ReflectedClass] instance for any given [Type].
///
/// This method is part of the [EmptyReflector] implementation and always
/// returns a constant instance of [_EmptyReflectedClass], regardless of
/// the input [clazz].
///
/// This behavior is consistent with the purpose of [EmptyReflector],
/// which provides non-functional placeholders for reflection operations.
///
/// @param clazz The [Type] to reflect, which is ignored in this implementation.
/// @return A constant [_EmptyReflectedClass] instance.
@override
ReflectedClass reflectClass(Type clazz) {
return const _EmptyReflectedClass();
}
/// Returns an empty [ReflectedInstance] for any given object.
///
/// This method is part of the [EmptyReflector] implementation and always
/// returns a constant instance of [_EmptyReflectedInstance], regardless of
/// the input [object].
///
/// This behavior is consistent with the purpose of [EmptyReflector],
/// which provides non-functional placeholders for reflection operations.
///
/// @param object The object to reflect, which is ignored in this implementation.
/// @return A constant [_EmptyReflectedInstance].
@override
ReflectedInstance reflectInstance(Object object) {
return const _EmptyReflectedInstance();
}
/// Returns an empty [ReflectedType] for any given [Type].
///
/// This method is part of the [EmptyReflector] implementation and always
/// returns a constant instance of [_EmptyReflectedType], regardless of
/// the input [type].
///
/// This behavior is consistent with the purpose of [EmptyReflector],
/// which provides non-functional placeholders for reflection operations.
///
/// @param type The [Type] to reflect, which is ignored in this implementation.
/// @return A constant [_EmptyReflectedType] instance.
@override
ReflectedType reflectType(Type type) {
return const _EmptyReflectedType();
}
/// Returns an empty [ReflectedFunction] for any given [Function].
///
/// This method is part of the [EmptyReflector] implementation and always
/// returns a constant instance of [_EmptyReflectedFunction], regardless of
/// the input [function].
///
/// This behavior is consistent with the purpose of [EmptyReflector],
/// which provides non-functional placeholders for reflection operations.
///
/// @param function The [Function] to reflect, which is ignored in this implementation.
/// @return A constant [_EmptyReflectedFunction] instance.
@override
ReflectedFunction reflectFunction(Function function) {
return const _EmptyReflectedFunction();
}
}
/// An empty implementation of [ReflectedClass] used by [EmptyReflector].
///
/// This class provides a non-functional placeholder for reflection operations
/// on classes. It is designed to be used in contexts where reflection capabilities
/// are expected but not actually needed or desired.
///
/// Key features:
/// - Extends [ReflectedClass] with minimal implementation.
/// - Constructor initializes with empty or default values for all properties.
/// - [newInstance] method throws an [UnsupportedError] if called.
/// - [isAssignableTo] method only returns true if compared with itself.
///
/// This implementation is consistent with the purpose of [EmptyReflector],
/// providing a lightweight alternative when full reflection capabilities are not required.
class _EmptyReflectedClass extends ReflectedClass {
/// Constructs an empty [_EmptyReflectedClass] instance.
///
/// This constructor initializes the instance with empty or default values for all properties.
///
/// @param name The name of the class, set to '(empty)'.
/// @param typeParameters The list of type parameters, set to an empty list.
/// @param instances The list of instances, set to an empty list.
/// @param functions The list of functions, set to an empty list.
/// @param declarations The list of declarations, set to an empty list.
/// @param type The underlying [Type] of the class, set to [Object].
const _EmptyReflectedClass()
: super(
'(empty)',
const <ReflectedTypeParameter>[],
const <ReflectedInstance>[],
const <ReflectedFunction>[],
const <ReflectedDeclaration>[],
Object);
/// Creates a new instance of the reflected class.
///
/// This method is part of the [_EmptyReflectedClass] implementation and always
/// throws an [UnsupportedError] when called. This behavior is consistent with
/// the purpose of [EmptyReflector], which provides non-functional placeholders
/// for reflection operations.
///
/// @param constructorName The name of the constructor to invoke.
/// @param positionalArguments A list of positional arguments for the constructor.
/// @param namedArguments An optional map of named arguments for the constructor.
/// @param typeArguments An optional list of type arguments for generic classes.
/// @throws UnsupportedError Always thrown when this method is called.
/// @return This method never returns as it always throws an exception.
@override
ReflectedInstance newInstance(
String constructorName, List positionalArguments,
[Map<String, dynamic>? namedArguments, List<Type>? typeArguments]) {
throw UnsupportedError(
'Classes reflected via an EmptyReflector cannot be instantiated.');
}
/// Checks if this empty reflected class is assignable to another reflected type.
///
/// This method is part of the [_EmptyReflectedClass] implementation and always
/// returns true only if the [other] type is the same instance as this one.
/// This behavior is consistent with the purpose of [EmptyReflector],
/// which provides minimal functionality for reflection operations.
///
/// @param other The [ReflectedType] to check against.
/// @return true if [other] is the same instance as this, false otherwise.
@override
bool isAssignableTo(ReflectedType? other) {
return other == this;
}
}
/// An empty implementation of [ReflectedType] used by [EmptyReflector].
///
/// This class provides a non-functional placeholder for reflection operations
/// on types. It is designed to be used in contexts where reflection capabilities
/// are expected but not actually needed or desired.
///
/// Key features:
/// - Extends [ReflectedType] with minimal implementation.
/// - Constructor initializes with empty or default values for all properties.
/// - [newInstance] method throws an [UnsupportedError] if called.
/// - [isAssignableTo] method only returns true if compared with itself.
///
/// This implementation is consistent with the purpose of [EmptyReflector],
/// providing a lightweight alternative when full reflection capabilities are not required.
class _EmptyReflectedType extends ReflectedType {
/// Constructs an empty [_EmptyReflectedType] instance.
///
/// This constructor initializes the instance with empty or default values for all properties.
///
/// @param name The name of the type, set to '(empty)'.
/// @param typeParameters The list of type parameters, set to an empty list.
/// @param type The underlying [Type], set to [Object].
const _EmptyReflectedType()
: super('(empty)', const <ReflectedTypeParameter>[], Object);
/// Creates a new instance of the reflected type.
///
/// This method is part of the [_EmptyReflectedType] implementation and always
/// throws an [UnsupportedError] when called. This behavior is consistent with
/// the purpose of [EmptyReflector], which provides non-functional placeholders
/// for reflection operations.
///
/// @param constructorName The name of the constructor to invoke.
/// @param positionalArguments A list of positional arguments for the constructor.
/// @param namedArguments An optional map of named arguments for the constructor.
/// @param typeArguments An optional list of type arguments for generic types.
/// @throws UnsupportedError Always thrown when this method is called.
/// @return This method never returns as it always throws an exception.
@override
ReflectedInstance newInstance(
String constructorName, List positionalArguments,
[Map<String, dynamic> namedArguments = const {},
List<Type> typeArguments = const []]) {
throw UnsupportedError(
'Types reflected via an EmptyReflector cannot be instantiated.');
}
/// Checks if this empty reflected type is assignable to another reflected type.
///
/// This method is part of the [_EmptyReflectedType] implementation and always
/// returns true only if the [other] type is the same instance as this one.
/// This behavior is consistent with the purpose of [EmptyReflector],
/// which provides minimal functionality for reflection operations.
///
/// @param other The [ReflectedType] to check against.
/// @return true if [other] is the same instance as this, false otherwise.
@override
bool isAssignableTo(ReflectedType? other) {
return other == this;
}
}
/// An empty implementation of [ReflectedInstance] used by [EmptyReflector].
///
/// This class provides a non-functional placeholder for reflection operations
/// on instances. It is designed to be used in contexts where reflection capabilities
/// are expected but not actually needed or desired.
///
/// Key features:
/// - Extends [ReflectedInstance] with minimal implementation.
/// - Constructor initializes with empty or default values for all properties.
/// - [getField] method throws an [UnsupportedError] if called.
///
/// This implementation is consistent with the purpose of [EmptyReflector],
/// providing a lightweight alternative when full reflection capabilities are not required.
class _EmptyReflectedInstance extends ReflectedInstance {
/// Constructs an empty [_EmptyReflectedInstance] instance.
///
/// This constructor initializes the instance with empty or default values for all properties.
///
/// @param type The reflected type of the instance, set to an empty [_EmptyReflectedType].
/// @param reflectedClass The reflected class of the instance, set to an empty [_EmptyReflectedClass].
/// @param value The underlying value of the instance, set to null.
const _EmptyReflectedInstance()
: super(const _EmptyReflectedType(), const _EmptyReflectedClass(), null);
/// Retrieves the value of a field on this empty reflected instance.
///
/// This method is part of the [_EmptyReflectedInstance] implementation and always
/// throws an [UnsupportedError] when called. This behavior is consistent with
/// the purpose of [EmptyReflector], which provides non-functional placeholders
/// for reflection operations.
///
/// @param name The name of the field to retrieve.
/// @throws UnsupportedError Always thrown when this method is called.
/// @return This method never returns as it always throws an exception.
@override
ReflectedInstance getField(String name) {
throw UnsupportedError(
'Instances reflected via an EmptyReflector cannot call getField().');
}
}
/// An empty implementation of [ReflectedFunction] used by [EmptyReflector].
///
/// This class provides a non-functional placeholder for reflection operations
/// on functions. It is designed to be used in contexts where reflection capabilities
/// are expected but not actually needed or desired.
///
/// Key features:
/// - Extends [ReflectedFunction] with minimal implementation.
/// - Constructor initializes with empty or default values for all properties.
/// - [invoke] method throws an [UnsupportedError] if called.
///
/// This implementation is consistent with the purpose of [EmptyReflector],
/// providing a lightweight alternative when full reflection capabilities are not required.
class _EmptyReflectedFunction extends ReflectedFunction {
/// Constructs an empty [_EmptyReflectedFunction] instance.
///
/// This constructor initializes the instance with empty or default values for all properties.
///
/// @param name The name of the function, set to an empty string.
/// @param typeParameters A list of type parameters for the function, set to an empty list.
/// @param enclosingInstance A list of enclosing instances for the function, set to an empty list.
/// @param parameters A list of parameters for the function, set to an empty list.
/// @param isStatic Indicates whether the function is static, set to false.
/// @param isConst Indicates whether the function is constant, set to false.
/// @param returnType The return type of the function, set to an empty [_EmptyReflectedType].
/// @param isOperator Indicates whether the function is an operator, set to false.
/// @param isExtensionMember Indicates whether the function is an extension member, set to false.
const _EmptyReflectedFunction()
: super(
'(empty)',
const <ReflectedTypeParameter>[],
const <ReflectedInstance>[],
const <ReflectedParameter>[],
false,
false,
returnType: const _EmptyReflectedType());
/// Invokes this empty reflected function.
///
/// This method is part of the [_EmptyReflectedFunction] implementation and always
/// throws an [UnsupportedError] when called. This behavior is consistent with
/// the purpose of [EmptyReflector], which provides non-functional placeholders
/// for reflection operations.
///
/// @param invocation The invocation to execute.
/// @throws UnsupportedError Always thrown when this method is called.
/// @return This method never returns as it always throws an exception.
@override
ReflectedInstance invoke(Invocation invocation) {
throw UnsupportedError(
'Instances reflected via an EmptyReflector cannot call invoke().');
}
}

View file

@ -1,34 +0,0 @@
/*
* This file is part of the Protevus Platform.
*
* (C) Protevus <developers@protevus.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/// A custom exception class for reflection-related errors.
///
/// This class extends the base [Exception] class and provides a way to
/// create exceptions specific to reflection operations. It includes a
/// message that describes the nature of the exception.
///
/// Example usage:
/// ```dart
/// throw ReflectionException('Failed to reflect on class XYZ');
/// ```
class ReflectionException implements Exception {
/// Creates a new instance of [ReflectionException] with the specified message.
///
/// The [message] parameter should describe the nature of the reflection error.
final String message;
/// Creates a new instance of [ReflectionException] with the specified message.
///
/// The [message] parameter should describe the nature of the reflection error.
ReflectionException(this.message);
// Override the toString method to provide a custom string representation of the exception.
@override
String toString() => message;
}

View file

@ -1,10 +0,0 @@
/*
* This file is part of the Protevus Platform.
*
* (C) Protevus <developers@protevus.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
export 'reflector.dart';

View file

@ -1,904 +0,0 @@
/*
* This file is part of the Protevus Platform.
*
* (C) Protevus <developers@protevus.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import 'dart:async';
import 'dart:mirrors' as dart;
import 'package:platform_container/container.dart';
import 'package:quiver/core.dart';
/// A [Reflector] implementation that forwards to `dart:mirrors`.
///
/// This class provides reflection capabilities by leveraging the `dart:mirrors` library.
/// It allows for runtime introspection of classes, functions, types, and instances.
///
/// Key features:
/// - Reflects classes, functions, types, and instances
/// - Provides access to class and function metadata
/// - Supports reflection of generic types and futures
/// - Allows invocation of reflected functions
///
/// Note: This reflector is primarily useful on the server-side where reflection is fully supported.
/// It may not be suitable for client-side Dart applications due to limitations in reflection support.
///
/// Usage:
/// ```dart
/// final reflector = MirrorsReflector();
/// final classReflection = reflector.reflectClass(MyClass);
/// final functionReflection = reflector.reflectFunction(myFunction);
/// final typeReflection = reflector.reflectType(int);
/// final instanceReflection = reflector.reflectInstance(myObject);
/// ```
///
/// Be aware of the performance implications when using reflection extensively,
/// as it can impact runtime performance and increase code size.
class MirrorsReflector extends Reflector {
/// Creates a new instance of [MirrorsReflector].
///
/// This constructor initializes the [MirrorsReflector] instance.
const MirrorsReflector();
/// Retrieves the name of a symbol as a string.
///
/// This method overrides the base implementation to use the `dart:mirrors` library
/// for converting a [Symbol] to its corresponding string representation.
///
/// Parameters:
/// - [symbol]: The [Symbol] whose name is to be retrieved.
///
/// Returns:
/// A [String] representing the name of the given symbol.
///
/// Example:
/// ```dart
/// final name = getName(#someSymbol);
/// print(name); // Outputs: "someSymbol"
/// ```
@override
String getName(Symbol symbol) => dart.MirrorSystem.getName(symbol);
/// Reflects a class and returns a [ReflectedClass] instance.
///
/// This method takes a [Type] parameter [clazz] and uses dart:mirrors to create
/// a reflection of the class. It returns a [_ReflectedClassMirror] which
/// implements [ReflectedClass].
///
/// Parameters:
/// - [clazz]: The [Type] of the class to reflect.
///
/// Returns:
/// A [ReflectedClass] instance representing the reflected class.
///
/// Throws:
/// - [ArgumentError] if the provided [clazz] is not a class.
///
/// Example:
/// ```dart
/// final reflector = MirrorsReflector();
/// final classReflection = reflector.reflectClass(MyClass);
/// ```
@override
ReflectedClass reflectClass(Type clazz) {
var mirror = dart.reflectType(clazz);
if (mirror is dart.ClassMirror) {
return _ReflectedClassMirror(mirror);
} else {
throw ArgumentError('$clazz is not a class.');
}
}
/// Reflects a function and returns a [ReflectedFunction] instance.
///
/// This method takes a [Function] parameter [function] and uses dart:mirrors to create
/// a reflection of the function. It returns a [_ReflectedMethodMirror] which
/// implements [ReflectedFunction].
///
/// Parameters:
/// - [function]: The [Function] to reflect.
///
/// Returns:
/// A [ReflectedFunction] instance representing the reflected function.
///
/// Example:
/// ```dart
/// final reflector = MirrorsReflector();
/// final functionReflection = reflector.reflectFunction(myFunction);
/// ```
@override
ReflectedFunction reflectFunction(Function function) {
var closure = dart.reflect(function) as dart.ClosureMirror;
return _ReflectedMethodMirror(closure.function, closure);
}
/// Reflects a given type and returns a [ReflectedType] instance.
///
/// This method takes a [Type] parameter and uses dart:mirrors to create
/// a reflection of the type. It returns either a [_ReflectedClassMirror]
/// or a [_ReflectedTypeMirror] depending on whether the reflected type
/// is a class or not.
///
/// Parameters:
/// - [type]: The [Type] to reflect.
///
/// Returns:
/// A [ReflectedType] instance representing the reflected type.
///
/// If the reflected type doesn't have a reflected type (i.e., [hasReflectedType] is false),
/// it returns a reflection of the `dynamic` type instead.
///
/// Example:
/// ```dart
/// final reflector = MirrorsReflector();
/// final typeReflection = reflector.reflectType(int);
/// ```
@override
ReflectedType reflectType(Type type) {
var mirror = dart.reflectType(type);
if (!mirror.hasReflectedType) {
return reflectType(dynamic);
} else {
if (mirror is dart.ClassMirror) {
return _ReflectedClassMirror(mirror);
} else {
return _ReflectedTypeMirror(mirror);
}
}
}
/// Reflects a Future of a given type and returns a [ReflectedType] instance.
///
/// This method takes a [Type] parameter and creates a reflection of a Future
/// that wraps that type. It first reflects the inner type, then constructs
/// a Future type with that inner type as its type argument.
///
/// Parameters:
/// - [type]: The [Type] to be wrapped in a Future.
///
/// Returns:
/// A [ReflectedType] instance representing the reflected Future<Type>.
///
/// Throws:
/// - [ArgumentError] if the provided [type] is not a class or type.
///
/// Example:
/// ```dart
/// final reflector = MirrorsReflector();
/// final futureIntReflection = reflector.reflectFutureOf(int);
/// // This will reflect Future<int>
/// ```
@override
ReflectedType reflectFutureOf(Type type) {
var inner = reflectType(type);
dart.TypeMirror localMirror;
if (inner is _ReflectedClassMirror) {
localMirror = inner.mirror;
} else if (inner is _ReflectedTypeMirror) {
localMirror = inner.mirror;
} else {
throw ArgumentError('$type is not a class or type.');
}
var future = dart.reflectType(Future, [localMirror.reflectedType]);
return _ReflectedClassMirror(future as dart.ClassMirror);
}
/// Reflects an instance of an object and returns a [ReflectedInstance].
///
/// This method takes an [Object] parameter and uses dart:mirrors to create
/// a reflection of the object instance. It returns a [_ReflectedInstanceMirror]
/// which implements [ReflectedInstance].
///
/// Parameters:
/// - [object]: The object instance to reflect.
///
/// Returns:
/// A [ReflectedInstance] representing the reflected object instance.
///
/// Example:
/// ```dart
/// final reflector = MirrorsReflector();
/// final instanceReflection = reflector.reflectInstance(myObject);
/// ```
@override
ReflectedInstance reflectInstance(Object object) {
return _ReflectedInstanceMirror(dart.reflect(object));
}
}
/// Represents a reflected type parameter using dart:mirrors.
///
/// This class extends [ReflectedTypeParameter] and wraps a [dart.TypeVariableMirror]
/// to provide reflection capabilities for type parameters in Dart.
///
/// The class extracts the name of the type parameter from the mirror and passes
/// it to the superclass constructor.
///
/// This is typically used internally by the reflection system to represent
/// type parameters of generic classes or methods.
class _ReflectedTypeParameter extends ReflectedTypeParameter {
/// The [dart.TypeVariableMirror] instance representing the reflected type parameter.
///
/// This mirror provides access to the details of the type parameter, such as its name,
/// bounds, and other metadata. It is used internally by the [_ReflectedTypeParameter]
/// class to implement reflection capabilities for type parameters.
final dart.TypeVariableMirror mirror;
/// Constructs a [_ReflectedTypeParameter] instance.
///
/// This constructor takes a [dart.TypeVariableMirror] and initializes the
/// [_ReflectedTypeParameter] with the name of the type parameter extracted
/// from the mirror.
///
/// Parameters:
/// - [mirror]: A [dart.TypeVariableMirror] representing the type parameter.
///
/// The constructor uses [dart.MirrorSystem.getName] to extract the name of the
/// type parameter from the mirror's [simpleName] and passes it to the superclass
/// constructor.
_ReflectedTypeParameter(this.mirror)
: super(dart.MirrorSystem.getName(mirror.simpleName));
}
/// Represents a reflected type using dart:mirrors.
///
/// This class extends [ReflectedType] and wraps a [dart.TypeMirror]
/// to provide reflection capabilities for types in Dart.
///
/// The class extracts the name and type variables from the mirror and passes
/// them to the superclass constructor. It also implements type comparison
/// through the [isAssignableTo] method.
///
/// Note that this class represents types that are not classes, and therefore
/// cannot be instantiated. Attempting to call [newInstance] will throw a
/// [ReflectionException].
///
/// This is typically used internally by the reflection system to represent
/// non-class types like interfaces, mixins, or type aliases.
class _ReflectedTypeMirror extends ReflectedType {
/// The [dart.TypeMirror] instance representing the reflected type.
///
/// This mirror provides access to the details of the type, such as its name,
/// type variables, and other metadata. It is used internally by the
/// [_ReflectedTypeMirror] class to implement reflection capabilities for types.
final dart.TypeMirror mirror;
/// Constructs a [_ReflectedTypeMirror] instance.
///
/// This constructor takes a [dart.TypeMirror] and initializes the
/// [_ReflectedTypeMirror] with the following:
/// - The name of the type extracted from the mirror's [simpleName].
/// - A list of [_ReflectedTypeParameter] objects created from the mirror's type variables.
/// - The reflected type of the mirror.
///
/// Parameters:
/// - [mirror]: A [dart.TypeMirror] representing the type to be reflected.
///
/// The constructor uses [dart.MirrorSystem.getName] to extract the name of the
/// type from the mirror's [simpleName]. It also maps the mirror's type variables
/// to [_ReflectedTypeParameter] objects and passes them along with the reflected
/// type to the superclass constructor.
_ReflectedTypeMirror(this.mirror)
: super(
dart.MirrorSystem.getName(mirror.simpleName),
mirror.typeVariables.map((m) => _ReflectedTypeParameter(m)).toList(),
mirror.reflectedType,
);
/// Checks if this reflected class is assignable to another reflected type.
///
/// This method determines whether an instance of this class can be assigned
/// to a variable of the type represented by [other].
///
/// Parameters:
/// - [other]: The [ReflectedType] to check against.
///
/// Returns:
/// - `true` if this class is assignable to [other].
/// - `false` otherwise, including when [other] is not a [_ReflectedClassMirror]
/// or [_ReflectedTypeMirror].
///
/// The method uses dart:mirrors' [isAssignableTo] to perform the actual check
/// when [other] is either a [_ReflectedClassMirror] or [_ReflectedTypeMirror].
@override
bool isAssignableTo(ReflectedType? other) {
if (other is _ReflectedClassMirror) {
return mirror.isAssignableTo(other.mirror);
} else if (other is _ReflectedTypeMirror) {
return mirror.isAssignableTo(other.mirror);
} else {
return false;
}
}
/// Throws a [ReflectionException] when attempting to create a new instance.
///
/// This method is intended to be overridden by classes that represent
/// instantiable types. For non-instantiable types (like interfaces or
/// abstract classes), this method throws an exception.
///
/// Parameters:
/// - [constructorName]: The name of the constructor to invoke.
/// - [positionalArguments]: A list of positional arguments for the constructor.
/// - [namedArguments]: An optional map of named arguments for the constructor.
/// - [typeArguments]: An optional list of type arguments for generic classes.
///
/// Throws:
/// [ReflectionException]: Always thrown with a message indicating that
/// this type cannot be instantiated.
///
/// Example:
/// ```dart
/// // This will always throw a ReflectionException
/// reflectedType.newInstance('defaultConstructor', []);
/// ```
@override
ReflectedInstance newInstance(
String constructorName, List positionalArguments,
[Map<String, dynamic>? namedArguments, List<Type>? typeArguments]) {
throw ReflectionException(
'$name is not a class, and therefore cannot be instantiated.');
}
}
/// Represents a reflected class using dart:mirrors.
///
/// This class extends [ReflectedClass] and wraps a [dart.ClassMirror]
/// to provide reflection capabilities for Dart classes.
///
/// Key features:
/// - Reflects class name, type parameters, constructors, and declarations
/// - Provides access to class metadata (annotations)
/// - Supports type comparison through [isAssignableTo]
/// - Allows creation of new instances of the reflected class
///
/// This class is typically used internally by the reflection system to
/// represent classes and their members.
class _ReflectedClassMirror extends ReflectedClass {
/// The [dart.ClassMirror] representing the reflected class.
///
/// This mirror is used to extract information about the class, such as
/// its name, type parameters, constructors, and declarations.
///
/// See also:
/// - [dart.ClassMirror] for more details about the mirror system.
final dart.ClassMirror mirror;
/// Constructs a [_ReflectedClassMirror] instance.
///
/// This constructor takes a [dart.ClassMirror] and initializes the
/// [_ReflectedClassMirror] with the following:
/// - The name of the class extracted from the mirror's [simpleName].
/// - A list of [_ReflectedTypeParameter] objects created from the mirror's type variables.
/// - Empty lists for constructors and annotations (these are populated elsewhere).
/// - A list of declarations obtained from the [_declarationsOf] method.
/// - The reflected type of the mirror.
///
/// Parameters:
/// - [mirror]: A [dart.ClassMirror] representing the class to be reflected.
///
/// The constructor uses [dart.MirrorSystem.getName] to extract the name of the
/// class from the mirror's [simpleName]. It also maps the mirror's type variables
/// to [_ReflectedTypeParameter] objects and uses [_declarationsOf] to get the
/// class declarations. These are then passed to the superclass constructor.
_ReflectedClassMirror(this.mirror)
: super(
dart.MirrorSystem.getName(mirror.simpleName),
mirror.typeVariables.map((m) => _ReflectedTypeParameter(m)).toList(),
[],
[],
_declarationsOf(mirror),
mirror.reflectedType,
);
/// Retrieves a list of reflected constructors from a given [dart.ClassMirror].
///
/// This static method iterates through the declarations of the provided [mirror],
/// identifies the constructor methods, and creates [ReflectedFunction] instances
/// for each constructor found.
///
/// Parameters:
/// - [mirror]: A [dart.ClassMirror] representing the class to examine.
///
/// Returns:
/// A [List] of [ReflectedFunction] objects, each representing a constructor
/// of the class.
///
/// The method specifically looks for [dart.MethodMirror] instances that are
/// marked as constructors (i.e., [isConstructor] is true). Each identified
/// constructor is wrapped in a [_ReflectedMethodMirror] and added to the
/// returned list.
static List<ReflectedFunction> _constructorsOf(dart.ClassMirror mirror) {
var out = <ReflectedFunction>[];
for (var key in mirror.declarations.keys) {
var value = mirror.declarations[key];
if (value is dart.MethodMirror && value.isConstructor) {
out.add(_ReflectedMethodMirror(value));
}
}
return out;
}
/// Retrieves a list of reflected declarations from a given [dart.ClassMirror].
///
/// This static method iterates through the declarations of the provided [mirror],
/// identifies non-constructor methods, and creates [ReflectedDeclaration] instances
/// for each method found.
///
/// Parameters:
/// - [mirror]: A [dart.ClassMirror] representing the class to examine.
///
/// Returns:
/// A [List] of [ReflectedDeclaration] objects, each representing a non-constructor
/// method of the class.
///
/// The method specifically looks for [dart.MethodMirror] instances that are
/// not constructors (i.e., [isConstructor] is false). Each identified
/// method is wrapped in a [_ReflectedDeclarationMirror] and added to the
/// returned list.
static List<ReflectedDeclaration> _declarationsOf(dart.ClassMirror mirror) {
var out = <ReflectedDeclaration>[];
for (var key in mirror.declarations.keys) {
var value = mirror.declarations[key];
if (value is dart.MethodMirror && !value.isConstructor) {
out.add(
_ReflectedDeclarationMirror(dart.MirrorSystem.getName(key), value));
}
}
return out;
}
/// Retrieves the annotations (metadata) associated with this reflected class.
///
/// This getter method overrides the base implementation to provide access to
/// the class-level annotations using dart:mirrors. It maps each metadata mirror
/// to a [_ReflectedInstanceMirror] and returns them as a list.
///
/// Returns:
/// A [List] of [ReflectedInstance] objects, each representing an annotation
/// applied to this class.
///
/// Example:
/// ```dart
/// @MyAnnotation()
/// class MyClass {}
///
/// // Assuming we have a reflection of MyClass
/// final classReflection = reflector.reflectClass(MyClass);
/// final annotations = classReflection.annotations;
/// // annotations will contain a ReflectedInstance of MyAnnotation
/// ```
///
/// Note: This method relies on the [dart.ClassMirror]'s metadata property
/// and creates a new [_ReflectedInstanceMirror] for each annotation.
@override
List<ReflectedInstance> get annotations =>
mirror.metadata.map((m) => _ReflectedInstanceMirror(m)).toList();
/// Retrieves a list of reflected constructors for this class.
///
/// This getter method overrides the base implementation to provide access to
/// the constructors of the reflected class using dart:mirrors. It uses the
/// static [_constructorsOf] method to extract and wrap each constructor
/// in a [ReflectedFunction] object.
///
/// Returns:
/// A [List] of [ReflectedFunction] objects, each representing a constructor
/// of this class.
///
/// Example:
/// ```dart
/// final classReflection = reflector.reflectClass(MyClass);
/// final constructors = classReflection.constructors;
/// // constructors will contain ReflectedFunction objects for each
/// // constructor in MyClass
/// ```
///
/// Note: This method relies on the [dart.ClassMirror]'s declarations and
/// the [_constructorsOf] method to identify and create reflections of
/// the class constructors.
@override
List<ReflectedFunction> get constructors => _constructorsOf(mirror);
/// Checks if this reflected type is assignable to another reflected type.
///
/// This method determines whether an instance of this type can be assigned
/// to a variable of the type represented by [other].
///
/// Parameters:
/// - [other]: The [ReflectedType] to check against.
///
/// Returns:
/// - `true` if this type is assignable to [other].
/// - `false` otherwise, including when [other] is not a [_ReflectedClassMirror]
/// or [_ReflectedTypeMirror].
///
/// The method uses dart:mirrors' [isAssignableTo] to perform the actual check
/// when [other] is either a [_ReflectedClassMirror] or [_ReflectedTypeMirror].
@override
bool isAssignableTo(ReflectedType? other) {
if (other is _ReflectedClassMirror) {
return mirror.isAssignableTo(other.mirror);
} else if (other is _ReflectedTypeMirror) {
return mirror.isAssignableTo(other.mirror);
} else {
return false;
}
}
/// Creates a new instance of the reflected class.
///
/// This method instantiates a new object of the class represented by this
/// [_ReflectedClassMirror] using the specified constructor and arguments.
///
/// Parameters:
/// - [constructorName]: The name of the constructor to invoke. Use an empty
/// string for the default constructor.
/// - [positionalArguments]: A list of positional arguments to pass to the constructor.
/// - [namedArguments]: An optional map of named arguments to pass to the constructor.
/// - [typeArguments]: An optional list of type arguments for generic classes.
///
/// Returns:
/// A [ReflectedInstance] representing the newly created instance.
///
/// Throws:
/// May throw exceptions if the constructor invocation fails, e.g., due to
/// invalid arguments or if the class cannot be instantiated.
///
/// Note:
/// This implementation currently does not use the [namedArguments] or
/// [typeArguments] parameters. They are included for API compatibility.
@override
ReflectedInstance newInstance(
String constructorName, List positionalArguments,
[Map<String, dynamic>? namedArguments, List<Type>? typeArguments]) {
return _ReflectedInstanceMirror(
mirror.newInstance(Symbol(constructorName), positionalArguments));
}
/// Checks if this [_ReflectedClassMirror] is equal to another object.
///
/// This method overrides the default equality operator to provide a custom
/// equality check for [_ReflectedClassMirror] instances.
///
/// Parameters:
/// - [other]: The object to compare with this [_ReflectedClassMirror].
///
/// Returns:
/// - `true` if [other] is also a [_ReflectedClassMirror] and has the same
/// [mirror] as this instance.
/// - `false` otherwise.
///
/// This implementation ensures that two [_ReflectedClassMirror] instances
/// are considered equal if and only if they reflect the same class (i.e.,
/// their underlying [dart.ClassMirror]s are the same).
@override
bool operator ==(other) {
return other is _ReflectedClassMirror && other.mirror == mirror;
}
/// Generates a hash code for this [_ReflectedClassMirror].
///
/// This method overrides the default [hashCode] implementation to provide
/// a consistent hash code for [_ReflectedClassMirror] instances.
///
/// The hash code is generated using the [hash2] function from the Quiver
/// library, combining the [mirror] object and an empty string. The empty
/// string is used as a second parameter to maintain compatibility with
/// the [hash2] function, which requires two arguments.
///
/// Returns:
/// An [int] representing the hash code of this [_ReflectedClassMirror].
///
/// Note:
/// This hash code implementation ensures that two [_ReflectedClassMirror]
/// instances with the same [mirror] will have the same hash code, which
/// is consistent with the equality check implemented in the [operator ==].
@override
int get hashCode => hash2(mirror, " ");
}
/// Represents a reflected declaration using dart:mirrors.
///
/// This class extends [ReflectedDeclaration] and wraps a [dart.MethodMirror]
/// to provide reflection capabilities for method declarations in Dart.
///
/// Key features:
/// - Reflects the name and static nature of the declaration
/// - Provides access to the underlying method as a [ReflectedFunction]
///
/// This class is typically used internally by the reflection system to
/// represent method declarations within a class.
class _ReflectedDeclarationMirror extends ReflectedDeclaration {
/// The [dart.MethodMirror] instance representing the reflected method.
///
/// This mirror provides access to the details of the method, such as its name,
/// parameters, return type, and other metadata. It is used internally by the
/// [_ReflectedDeclarationMirror] class to implement reflection capabilities
/// for method declarations.
final dart.MethodMirror mirror;
/// Constructs a [_ReflectedDeclarationMirror] instance.
///
/// This constructor initializes a new [_ReflectedDeclarationMirror] with the given [name]
/// and [mirror]. It uses the [dart.MethodMirror]'s [isStatic] property to determine
/// if the declaration is static, and passes `null` as the initial value for the function.
///
/// Parameters:
/// - [name]: A [String] representing the name of the declaration.
/// - [mirror]: A [dart.MethodMirror] representing the reflected method.
///
/// The constructor calls the superclass constructor with the provided [name],
/// the [isStatic] property from the [mirror], and `null` for the function parameter.
_ReflectedDeclarationMirror(String name, this.mirror)
: super(name, mirror.isStatic, null);
/// Determines if this declaration is static.
///
/// This getter overrides the base implementation to provide information
/// about whether the reflected declaration is static or not. It directly
/// accesses the [isStatic] property of the underlying [dart.MethodMirror].
///
/// Returns:
/// A [bool] value:
/// - `true` if the declaration is static.
/// - `false` if the declaration is not static (i.e., it's an instance method).
///
/// This property is useful for determining the nature of the reflected
/// declaration, particularly when working with class methods and properties.
@override
bool get isStatic => mirror.isStatic;
/// Retrieves a [ReflectedFunction] representation of this declaration.
///
/// This getter overrides the base implementation to provide a [ReflectedFunction]
/// that represents the method associated with this declaration. It creates a new
/// [_ReflectedMethodMirror] instance using the underlying [dart.MethodMirror].
///
/// Returns:
/// A [ReflectedFunction] object that represents the method of this declaration.
///
/// This property is useful for accessing detailed information about the method,
/// such as its parameters, return type, and other attributes, in a way that's
/// consistent with the reflection API.
@override
ReflectedFunction get function => _ReflectedMethodMirror(mirror);
}
/// Represents a reflected instance of an object using dart:mirrors.
///
/// This class extends [ReflectedInstance] and wraps a [dart.InstanceMirror]
/// to provide reflection capabilities for object instances in Dart.
///
/// Key features:
/// - Reflects the type and runtime type of the instance
/// - Provides access to the underlying object (reflectee)
/// - Allows retrieval of field values through reflection
///
/// This class is typically used internally by the reflection system to
/// represent instances of objects and provide reflective access to their fields.
class _ReflectedInstanceMirror extends ReflectedInstance {
/// The [dart.InstanceMirror] representing the reflected instance.
///
/// This mirror provides access to the details of the object instance, such as its type,
/// fields, and methods. It is used internally by the [_ReflectedInstanceMirror] class
/// to implement reflection capabilities for object instances.
///
/// The mirror allows for dynamic inspection and manipulation of the object's state
/// and behavior at runtime, enabling powerful reflection features.
final dart.InstanceMirror mirror;
/// Constructs a [_ReflectedInstanceMirror] instance.
///
/// This constructor initializes a new [_ReflectedInstanceMirror] with the given [mirror].
/// It uses the [dart.InstanceMirror]'s [type] property to create [_ReflectedClassMirror]
/// instances for both the type and runtime type of the reflected instance.
///
/// Parameters:
/// - [mirror]: A [dart.InstanceMirror] representing the reflected instance.
///
/// The constructor calls the superclass constructor with:
/// - A [_ReflectedClassMirror] of the instance's type
/// - A [_ReflectedClassMirror] of the instance's runtime type
/// - The [reflectee] of the mirror, which is the actual object being reflected
///
/// This setup allows the [_ReflectedInstanceMirror] to provide access to both
/// the compile-time and runtime type information of the reflected instance,
/// as well as the underlying object itself.
_ReflectedInstanceMirror(this.mirror)
: super(_ReflectedClassMirror(mirror.type),
_ReflectedClassMirror(mirror.type), mirror.reflectee);
/// Retrieves the value of a field from the reflected instance.
///
/// This method allows access to field values of the object represented by this
/// [_ReflectedInstanceMirror] through reflection.
///
/// Parameters:
/// - [name]: A [String] representing the name of the field to retrieve.
///
/// Returns:
/// A [ReflectedInstance] representing the value of the specified field.
/// This returned instance is wrapped in a [_ReflectedInstanceMirror].
///
/// Throws:
/// May throw exceptions if the field does not exist or if access is not allowed.
///
/// Example:
/// ```dart
/// var fieldValue = reflectedInstance.getField('myField');
/// ```
///
/// Note:
/// This method uses the underlying [dart.InstanceMirror]'s [getField] method
/// to perform the actual field access.
@override
ReflectedInstance getField(String name) {
return _ReflectedInstanceMirror(mirror.getField(Symbol(name)));
}
}
/// Represents a reflected method using dart:mirrors.
///
/// This class extends [ReflectedFunction] and wraps a [dart.MethodMirror]
/// to provide reflection capabilities for methods in Dart.
///
/// Key features:
/// - Reflects method name, parameters, and return type
/// - Provides access to method metadata (annotations)
/// - Supports invocation of the reflected method (if a ClosureMirror is available)
///
/// The class uses both [dart.MethodMirror] and optionally [dart.ClosureMirror]
/// to represent and potentially invoke the reflected method.
///
/// Usage:
/// - Created internally by the reflection system to represent methods
/// - Can be used to inspect method details or invoke the method if a ClosureMirror is provided
///
/// Note:
/// - Invocation is only possible if a ClosureMirror is provided during construction
/// - Throws a StateError if invoke is called without a ClosureMirror
class _ReflectedMethodMirror extends ReflectedFunction {
/// The [dart.MethodMirror] instance representing the reflected method.
///
/// This mirror provides access to the details of the method, such as its name,
/// parameters, return type, and other metadata. It is used internally by the
/// [_ReflectedMethodMirror] class to implement reflection capabilities
/// for methods.
///
/// The [dart.MethodMirror] is a crucial component in the reflection process,
/// allowing for introspection of method properties and behavior at runtime.
final dart.MethodMirror mirror;
/// An optional [dart.ClosureMirror] representing the closure of the reflected method.
///
/// This field is used to store a [dart.ClosureMirror] when the reflected method
/// is associated with a callable object (i.e., a closure). The presence of this
/// mirror enables the [invoke] method to directly call the reflected method.
///
/// If this field is null, it indicates that the reflected method cannot be
/// directly invoked through this [_ReflectedMethodMirror] instance.
///
/// Note:
/// - This field is crucial for supporting method invocation via reflection.
/// - It's typically set when reflecting on instance methods or standalone functions.
/// - For class-level method declarations that aren't bound to an instance,
/// this field may be null.
final dart.ClosureMirror? closureMirror;
/// Constructs a [_ReflectedMethodMirror] instance.
///
/// This constructor initializes a new [_ReflectedMethodMirror] with the given [mirror]
/// and optional [closureMirror]. It extracts various properties from the [dart.MethodMirror]
/// to populate the superclass constructor.
///
/// Parameters:
/// - [mirror]: A [dart.MethodMirror] representing the reflected method.
/// - [closureMirror]: An optional [dart.ClosureMirror] for method invocation.
///
/// The constructor initializes the following:
/// - Method name from the mirror's [simpleName]
/// - An empty list of reflected type parameters
/// - Metadata (annotations) as [_ReflectedInstanceMirror] objects
/// - Reflected parameters using [_reflectParameter]
/// - Getter and setter flags from the mirror
/// - Return type, using [dynamic] if the mirror doesn't have a reflected type
///
/// This setup allows the [_ReflectedMethodMirror] to provide comprehensive
/// reflection capabilities for the method, including its signature, metadata,
/// and potential invocation (if a [closureMirror] is provided).
_ReflectedMethodMirror(this.mirror, [this.closureMirror])
: super(
dart.MirrorSystem.getName(mirror.simpleName),
<ReflectedTypeParameter>[],
mirror.metadata
.map((mirror) => _ReflectedInstanceMirror(mirror))
.toList(),
mirror.parameters.map(_reflectParameter).toList(),
mirror.isGetter,
mirror.isSetter,
returnType: !mirror.returnType.hasReflectedType
? const MirrorsReflector().reflectType(dynamic)
: const MirrorsReflector()
.reflectType(mirror.returnType.reflectedType));
/// Reflects a parameter of a method using dart:mirrors.
///
/// This static method creates a [ReflectedParameter] instance from a given [dart.ParameterMirror].
/// It extracts various properties from the mirror to construct a comprehensive reflection of the parameter.
///
/// Parameters:
/// - [mirror]: A [dart.ParameterMirror] representing the parameter to be reflected.
///
/// Returns:
/// A [ReflectedParameter] instance containing the reflected information of the parameter.
///
/// The method extracts the following information:
/// - Parameter name from the mirror's [simpleName]
/// - Metadata (annotations) as [_ReflectedInstanceMirror] objects
/// - Parameter type, reflected using [MirrorsReflector]
/// - Whether the parameter is required (not optional)
/// - Whether the parameter is named
///
/// This method is typically used internally by the reflection system to create
/// parameter reflections for method signatures.
static ReflectedParameter _reflectParameter(dart.ParameterMirror mirror) {
return ReflectedParameter(
dart.MirrorSystem.getName(mirror.simpleName),
mirror.metadata
.map((mirror) => _ReflectedInstanceMirror(mirror))
.toList(),
const MirrorsReflector().reflectType(mirror.type.reflectedType),
!mirror.isOptional,
mirror.isNamed);
}
/// Invokes the reflected method with the given invocation details.
///
/// This method allows for dynamic invocation of the reflected method using the
/// provided [Invocation] object. It requires that a [closureMirror] was provided
/// during the construction of this [_ReflectedMethodMirror].
///
/// Parameters:
/// - [invocation]: An [Invocation] object containing the details of the method call,
/// including the method name, positional arguments, and named arguments.
///
/// Returns:
/// A [ReflectedInstance] representing the result of the method invocation.
///
/// Throws:
/// - [StateError] if this [_ReflectedMethodMirror] was created without a [closureMirror],
/// indicating that direct invocation is not possible.
///
/// Example:
/// ```dart
/// var result = reflectedMethod.invoke(Invocation.method(#methodName, [arg1, arg2]));
/// ```
///
/// Note:
/// This method relies on the presence of a [closureMirror] to perform the actual
/// invocation. If no [closureMirror] is available, it means the reflected method
/// cannot be directly invoked, and an error will be thrown.
@override
ReflectedInstance invoke(Invocation invocation) {
if (closureMirror == null) {
throw StateError(
'This object was reflected without a ClosureMirror, and therefore cannot be directly invoked.');
}
return _ReflectedInstanceMirror(closureMirror!.invoke(invocation.memberName,
invocation.positionalArguments, invocation.namedArguments));
}
}

View file

@ -1,8 +0,0 @@
/*
* This file is part of the Protevus Platform.
*
* (C) Protevus <developers@protevus.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

View file

@ -1,298 +0,0 @@
/*
* This file is part of the Protevus Platform.
*
* (C) Protevus <developers@protevus.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import 'package:collection/collection.dart';
import 'package:quiver/core.dart';
/// Abstract class representing a reflector for introspection of Dart types and instances.
///
/// This class provides methods to reflect on various Dart constructs such as classes,
/// functions, types, and instances. It allows for runtime inspection and manipulation
/// of code elements.
///
/// The methods in this class are designed to be implemented by concrete reflector
/// classes, potentially using different reflection mechanisms (e.g., mirrors, code
/// generation).
///
/// Note: The `reflectFutureOf` method throws an `UnsupportedError` by default and
/// requires `dart:mirrors` for implementation.
abstract class Reflector {
/// Constructs a new [Reflector] instance.
///
/// This constructor is declared as `const` to allow for compile-time constant creation
/// of [Reflector] instances. Subclasses of [Reflector] may override this constructor
/// to provide their own initialization logic if needed.
const Reflector();
String? getName(Symbol symbol);
ReflectedClass? reflectClass(Type clazz);
ReflectedFunction? reflectFunction(Function function);
ReflectedType? reflectType(Type type);
ReflectedInstance? reflectInstance(Object object);
ReflectedType reflectFutureOf(Type type) {
throw UnsupportedError('`reflectFutureOf` requires `dart:mirrors`.');
}
}
/// Represents a reflected instance of an object.
///
/// This abstract class provides a way to introspect and manipulate object instances
/// at runtime. It encapsulates information about the object's type, class, and the
/// actual object instance (reflectee).
///
/// The [type] property represents the reflected type of the instance.
/// The [clazz] property represents the reflected class of the instance.
/// The [reflectee] property holds the actual object instance being reflected.
///
/// This class also provides methods for comparing instances and accessing fields.
///
/// Use the [getField] method to retrieve a reflected instance of a specific field.
abstract class ReflectedInstance {
final ReflectedType type;
final ReflectedClass clazz;
final Object? reflectee;
const ReflectedInstance(this.type, this.clazz, this.reflectee);
@override
int get hashCode => hash2(type, clazz);
@override
bool operator ==(other) =>
other is ReflectedInstance && other.type == type && other.clazz == clazz;
ReflectedInstance getField(String name);
}
/// Represents a reflected type in the Dart language.
///
/// This abstract class encapsulates information about a Dart type, including its name,
/// type parameters, and the actual Dart [Type] it represents.
///
/// The [name] property holds the name of the type.
/// The [typeParameters] list contains the type parameters if the type is generic.
/// The [reflectedType] property holds the actual Dart [Type] being reflected.
///
/// This class provides methods for creating new instances of the type, comparing types,
/// and checking type assignability.
///
/// The [newInstance] method allows for dynamic creation of new instances of the type.
/// The [isAssignableTo] method checks if this type is assignable to another type.
///
/// This class also overrides [hashCode] and [operator ==] for proper equality comparisons.
abstract class ReflectedType {
final String name;
final List<ReflectedTypeParameter> typeParameters;
final Type reflectedType;
const ReflectedType(this.name, this.typeParameters, this.reflectedType);
@override
int get hashCode => hash3(name, typeParameters, reflectedType);
@override
bool operator ==(other) =>
other is ReflectedType &&
other.name == name &&
const ListEquality<ReflectedTypeParameter>()
.equals(other.typeParameters, typeParameters) &&
other.reflectedType == reflectedType;
ReflectedInstance newInstance(
String constructorName, List positionalArguments,
[Map<String, dynamic> namedArguments = const {},
List<Type> typeArguments = const []]);
bool isAssignableTo(ReflectedType? other);
}
/// Represents a reflected class in the Dart language.
///
/// This abstract class extends [ReflectedType] and provides additional information
/// specific to classes, including annotations, constructors, and declarations.
///
/// The [annotations] list contains reflected instances of annotations applied to the class.
/// The [constructors] list contains reflected functions representing the class constructors.
/// The [declarations] list contains reflected declarations (fields, methods, etc.) of the class.
///
/// This class overrides [hashCode] and [operator ==] to include the additional properties
/// in equality comparisons and hash code calculations.
abstract class ReflectedClass extends ReflectedType {
final List<ReflectedInstance> annotations;
final List<ReflectedFunction> constructors;
final List<ReflectedDeclaration> declarations;
const ReflectedClass(
String name,
List<ReflectedTypeParameter> typeParameters,
this.annotations,
this.constructors,
this.declarations,
Type reflectedType)
: super(name, typeParameters, reflectedType);
@override
int get hashCode =>
hash4(super.hashCode, annotations, constructors, declarations);
@override
bool operator ==(other) =>
other is ReflectedClass &&
super == other &&
const ListEquality<ReflectedInstance>()
.equals(other.annotations, annotations) &&
const ListEquality<ReflectedFunction>()
.equals(other.constructors, constructors) &&
const ListEquality<ReflectedDeclaration>()
.equals(other.declarations, declarations);
}
/// Represents a reflected declaration in the Dart language.
///
/// This class encapsulates information about a declaration within a class or object,
/// such as a method, field, or property.
///
/// The [name] property holds the name of the declaration.
/// The [isStatic] property indicates whether the declaration is static.
/// The [function] property, if non-null, represents the reflected function associated
/// with this declaration (applicable for methods and some properties).
///
/// This class provides methods for comparing declarations and calculating hash codes.
/// It overrides [hashCode] and [operator ==] for proper equality comparisons.
class ReflectedDeclaration {
final String name;
final bool isStatic;
final ReflectedFunction? function;
const ReflectedDeclaration(this.name, this.isStatic, this.function);
@override
int get hashCode => hash3(name, isStatic, function);
@override
bool operator ==(other) =>
other is ReflectedDeclaration &&
other.name == name &&
other.isStatic == isStatic &&
other.function == function;
}
/// Represents a reflected function in the Dart language.
///
/// This abstract class encapsulates information about a function, including its name,
/// type parameters, annotations, return type, parameters, and whether it's a getter or setter.
///
/// The [name] property holds the name of the function.
/// The [typeParameters] list contains the type parameters if the function is generic.
/// The [annotations] list contains reflected instances of annotations applied to the function.
/// The [returnType] property represents the function's return type (if applicable).
/// The [parameters] list contains the function's parameters.
/// The [isGetter] and [isSetter] properties indicate if the function is a getter or setter.
///
/// This class provides methods for comparing functions and calculating hash codes.
/// It also includes an [invoke] method for dynamically calling the function.
///
/// This class overrides [hashCode] and [operator ==] for proper equality comparisons.
abstract class ReflectedFunction {
final String name;
final List<ReflectedTypeParameter> typeParameters;
final List<ReflectedInstance> annotations;
final ReflectedType? returnType;
final List<ReflectedParameter> parameters;
final bool isGetter, isSetter;
const ReflectedFunction(this.name, this.typeParameters, this.annotations,
this.parameters, this.isGetter, this.isSetter,
{this.returnType});
@override
int get hashCode => hashObjects([
name,
typeParameters,
annotations,
returnType,
parameters,
isGetter,
isSetter
]);
@override
bool operator ==(other) =>
other is ReflectedFunction &&
other.name == name &&
const ListEquality<ReflectedTypeParameter>()
.equals(other.typeParameters, typeParameters) &&
const ListEquality<ReflectedInstance>()
.equals(other.annotations, annotations) &&
other.returnType == returnType &&
const ListEquality<ReflectedParameter>()
.equals(other.parameters, other.parameters) &&
other.isGetter == isGetter &&
other.isSetter == isSetter;
ReflectedInstance invoke(Invocation invocation);
}
/// Represents a reflected parameter in the Dart language.
///
/// This class encapsulates information about a function or method parameter,
/// including its name, annotations, type, and properties such as whether it's
/// required or named.
///
/// Properties:
/// - [name]: The name of the parameter.
/// - [annotations]: A list of reflected instances of annotations applied to the parameter.
/// - [type]: The reflected type of the parameter.
/// - [isRequired]: Indicates whether the parameter is required.
/// - [isNamed]: Indicates whether the parameter is a named parameter.
///
/// This class provides methods for comparing parameters and calculating hash codes.
/// It overrides [hashCode] and [operator ==] for proper equality comparisons.
class ReflectedParameter {
final String name;
final List<ReflectedInstance> annotations;
final ReflectedType type;
final bool isRequired;
final bool isNamed;
const ReflectedParameter(
this.name, this.annotations, this.type, this.isRequired, this.isNamed);
@override
int get hashCode =>
hashObjects([name, annotations, type, isRequired, isNamed]);
@override
bool operator ==(other) =>
other is ReflectedParameter &&
other.name == name &&
const ListEquality<ReflectedInstance>()
.equals(other.annotations, annotations) &&
other.type == type &&
other.isRequired == isRequired &&
other.isNamed == isNamed;
}
class ReflectedTypeParameter {
final String name;
const ReflectedTypeParameter(this.name);
@override
int get hashCode => hashObjects([name]);
@override
bool operator ==(other) =>
other is ReflectedTypeParameter && other.name == name;
}

View file

@ -1,179 +0,0 @@
/*
* This file is part of the Protevus Platform.
*
* (C) Protevus <developers@protevus.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import 'package:platform_container/container.dart';
/// A static implementation of the [Reflector] class that performs simple [Map] lookups.
///
/// `package:platform_container_generator` uses this to create reflectors from analysis metadata.
class StaticReflector extends Reflector {
/// A map that associates [Symbol] objects with their corresponding string names.
///
/// This map is used to store and retrieve the string representations of symbols,
/// which can be useful for reflection and debugging purposes.
final Map<Symbol, String> names;
/// A map that associates [Type] objects with their corresponding [ReflectedType] objects.
///
/// This map is used to store and retrieve reflection information for different types,
/// allowing for runtime introspection of type metadata and structure.
final Map<Type, ReflectedType> types;
/// A map that associates [Function] objects with their corresponding [ReflectedFunction] objects.
///
/// This map is used to store and retrieve reflection information for functions,
/// enabling runtime introspection of function metadata, parameters, and return types.
final Map<Function, ReflectedFunction> functions;
/// A map that associates [Object] instances with their corresponding [ReflectedInstance] objects.
///
/// This map is used to store and retrieve reflection information for specific object instances,
/// allowing for runtime introspection of object properties, methods, and metadata.
final Map<Object, ReflectedInstance> instances;
/// Creates a new [StaticReflector] instance with optional parameters.
///
/// The [StaticReflector] constructor allows you to initialize the reflector
/// with pre-populated maps for names, types, functions, and instances.
///
/// Parameters:
/// - [names]: A map of [Symbol] to [String] for symbol name lookups. Defaults to an empty map.
/// - [types]: A map of [Type] to [ReflectedType] for type reflection. Defaults to an empty map.
/// - [functions]: A map of [Function] to [ReflectedFunction] for function reflection. Defaults to an empty map.
/// - [instances]: A map of [Object] to [ReflectedInstance] for instance reflection. Defaults to an empty map.
///
/// All parameters are optional and default to empty constant maps if not provided.
const StaticReflector(
{this.names = const {},
this.types = const {},
this.functions = const {},
this.instances = const {}});
/// Returns the string name associated with the given [Symbol].
///
/// This method looks up the string representation of the provided [symbol]
/// in the [names] map. If the symbol is found, its corresponding string
/// name is returned. If the symbol is not found in the map, an [ArgumentError]
/// is thrown.
///
/// Parameters:
/// - [symbol]: The [Symbol] for which to retrieve the string name.
///
/// Returns:
/// The string name associated with the given [symbol], or null if not found.
///
/// Throws:
/// - [ArgumentError]: If the provided [symbol] is not found in the [names] map.
@override
String? getName(Symbol symbol) {
if (!names.containsKey(symbol)) {
throw ArgumentError(
'The value of $symbol is unknown - it was not generated.');
}
return names[symbol];
}
/// Reflects a class based on its [Type].
///
/// This method attempts to reflect the given class [Type] by calling [reflectType]
/// and casting the result to [ReflectedClass]. If the reflection is successful
/// and the result is a [ReflectedClass], it is returned. Otherwise, null is returned.
///
/// Parameters:
/// - [clazz]: The [Type] of the class to reflect.
///
/// Returns:
/// A [ReflectedClass] instance if the reflection is successful and the result
/// is a [ReflectedClass], or null otherwise.
@override
ReflectedClass? reflectClass(Type clazz) =>
reflectType(clazz) as ReflectedClass?;
/// Reflects a function based on its [Function] object.
///
/// This method attempts to retrieve reflection information for the given [function]
/// from the [functions] map. If the function is found in the map, its corresponding
/// [ReflectedFunction] object is returned. If the function is not found, an
/// [ArgumentError] is thrown.
///
/// Parameters:
/// - [function]: The [Function] object to reflect.
///
/// Returns:
/// A [ReflectedFunction] object containing reflection information about the
/// given function, or null if not found.
///
/// Throws:
/// - [ArgumentError]: If there is no reflection information available for
/// the given [function].
@override
ReflectedFunction? reflectFunction(Function function) {
if (!functions.containsKey(function)) {
throw ArgumentError(
'There is no reflection information available about $function.');
}
return functions[function];
}
/// Reflects an object instance to retrieve its reflection information.
///
/// This method attempts to retrieve reflection information for the given [object]
/// from the [instances] map. If the object is found in the map, its corresponding
/// [ReflectedInstance] object is returned. If the object is not found, an
/// [ArgumentError] is thrown.
///
/// Parameters:
/// - [object]: The object instance to reflect.
///
/// Returns:
/// A [ReflectedInstance] object containing reflection information about the
/// given object instance, or null if not found.
///
/// Throws:
/// - [ArgumentError]: If there is no reflection information available for
/// the given [object].
@override
ReflectedInstance? reflectInstance(Object object) {
if (!instances.containsKey(object)) {
throw ArgumentError(
'There is no reflection information available about $object.');
}
return instances[object];
}
/// Reflects a type to retrieve its reflection information.
///
/// This method attempts to retrieve reflection information for the given [type]
/// from the [types] map. If the type is found in the map, its corresponding
/// [ReflectedType] object is returned. If the type is not found, an
/// [ArgumentError] is thrown.
///
/// Parameters:
/// - [type]: The [Type] to reflect.
///
/// Returns:
/// A [ReflectedType] object containing reflection information about the
/// given type, or null if not found.
///
/// Throws:
/// - [ArgumentError]: If there is no reflection information available for
/// the given [type].
@override
ReflectedType? reflectType(Type type) {
if (!types.containsKey(type)) {
throw ArgumentError(
'There is no reflection information available about $type.');
}
return types[type];
}
}

View file

@ -1,93 +0,0 @@
import 'package:platform_container/src/container_const.dart';
import 'empty/empty.dart';
import 'reflector.dart';
/// A [Reflector] implementation that throws exceptions on all attempts
/// to perform reflection.
///
/// Use this in contexts where you know you won't need any reflective capabilities.
class ThrowingReflector extends Reflector {
/// The error message to give the end user when an [UnsupportedError] is thrown.
final String errorMessage;
/*
static const String defaultErrorMessage =
'You attempted to perform a reflective action, but you are using `ThrowingReflector`, '
'a class which disables reflection. Consider using the `MirrorsReflector` '
'class if you need reflection.';
*/
/// Creates a [ThrowingReflector] instance.
///
/// [errorMessage] is the message to be used when throwing an [UnsupportedError].
/// If not provided, it defaults to [ContainerConst.defaultErrorMessage].
const ThrowingReflector(
{this.errorMessage = ContainerConst.defaultErrorMessage});
/// Retrieves the name associated with the given [symbol].
///
/// This method delegates the task to an instance of [EmptyReflector].
/// It returns the name as a [String] if found, or `null` if not found.
///
/// [symbol] is the [Symbol] for which to retrieve the name.
///
/// Returns a [String] representing the name of the symbol, or `null` if not found.
@override
String? getName(Symbol symbol) => const EmptyReflector().getName(symbol);
/// Creates and returns an [UnsupportedError] with the specified [errorMessage].
///
/// This method is used internally to generate consistent error messages
/// when reflection operations are attempted on this [ThrowingReflector].
///
/// Returns an [UnsupportedError] instance with the configured error message.
UnsupportedError _error() => UnsupportedError(errorMessage);
/// Reflects on a given class type and throws an [UnsupportedError].
///
/// This method is part of the [ThrowingReflector] implementation and is designed
/// to prevent reflective operations. When called, it throws an [UnsupportedError]
/// with the configured error message.
///
/// [clazz] is the [Type] of the class to reflect on.
///
/// Throws an [UnsupportedError] when invoked, as reflection is not supported.
@override
ReflectedClass reflectClass(Type clazz) => throw _error();
/// Reflects on a given object instance and throws an [UnsupportedError].
///
/// This method is part of the [ThrowingReflector] implementation and is designed
/// to prevent reflective operations on object instances. When called, it throws
/// an [UnsupportedError] with the configured error message.
///
/// [object] is the object instance to reflect on.
///
/// Throws an [UnsupportedError] when invoked, as reflection is not supported.
@override
ReflectedInstance reflectInstance(Object object) => throw _error();
/// Reflects on a given type and throws an [UnsupportedError].
///
/// This method is part of the [ThrowingReflector] implementation and is designed
/// to prevent reflective operations on types. When called, it throws an
/// [UnsupportedError] with the configured error message.
///
/// [type] is the [Type] to reflect on.
///
/// Throws an [UnsupportedError] when invoked, as reflection is not supported.
@override
ReflectedType reflectType(Type type) => throw _error();
/// Reflects on a given function and throws an [UnsupportedError].
///
/// This method is part of the [ThrowingReflector] implementation and is designed
/// to prevent reflective operations on functions. When called, it throws an
/// [UnsupportedError] with the configured error message.
///
/// [function] is the [Function] to reflect on.
///
/// Throws an [UnsupportedError] when invoked, as reflection is not supported.
@override
ReflectedFunction reflectFunction(Function function) => throw _error();
}

View file

@ -1,14 +0,0 @@
name: platform_container
version: 9.0.0
description: Protevus Platform hierarchical DI container, and pluggable backends for reflection.
homepage: https://protevus.com
documentation: https://docs.protevus.com
repository: https://git.protevus.com/protevus/platform/src/branch/main/packages/container/container
environment:
sdk: '>=3.3.0 <4.0.0'
dependencies:
collection: ^1.19.1
quiver: ^3.2.2
dev_dependencies:
test: ^1.25.8
lints: ^4.0.0

View file

@ -1,122 +0,0 @@
import 'dart:async';
import 'package:platform_container/container.dart';
import 'package:test/test.dart';
void returnVoidFromAFunction(int x) {}
void testReflector(Reflector reflector) {
var blaziken = Pokemon('Blaziken', PokemonType.fire);
late Container container;
setUp(() {
container = Container(reflector);
container.registerSingleton(blaziken);
container.registerFactory<Future<int>>((_) async => 46);
});
test('get field', () {
var blazikenMirror = reflector.reflectInstance(blaziken)!;
expect(blazikenMirror.getField('type').reflectee, blaziken.type);
});
group('reflectFunction', () {
var mirror = reflector.reflectFunction(returnVoidFromAFunction);
test('void return type returns dynamic', () {
expect(mirror!.returnType, reflector.reflectType(dynamic));
});
test('counts parameters', () {
expect(mirror!.parameters, hasLength(1));
});
test('counts types parameters', () {
expect(mirror!.typeParameters, isEmpty);
});
test('correctly reflects parameter types', () {
var p = mirror!.parameters[0];
expect(p.name, 'x');
expect(p.isRequired, true);
expect(p.isNamed, false);
expect(p.annotations, isEmpty);
expect(p.type, reflector.reflectType(int));
});
});
test('make on singleton type returns singleton', () {
expect(container.make(Pokemon), blaziken);
});
test('make with generic returns same as make with explicit type', () {
expect(container.make<Pokemon>(), blaziken);
});
test('make async returns async object', () async {
expect(container.makeAsync<int>(), completion(46));
});
test('make async returns sync object', () async {
expect(container.makeAsync<Pokemon>(), completion(blaziken));
});
test('make on aliased singleton returns singleton', () {
container.registerSingleton(blaziken, as: StateError);
expect(container.make(StateError), blaziken);
});
test('constructor injects singleton', () {
var lower = container.make<LowerPokemon>();
expect(lower.lowercaseName, blaziken.name.toLowerCase());
});
test('newInstance works', () {
var type = container.reflector.reflectType(Pokemon)!;
var instance =
type.newInstance('changeName', [blaziken, 'Charizard']).reflectee
as Pokemon;
print(instance);
expect(instance.name, 'Charizard');
expect(instance.type, PokemonType.fire);
});
test('isAssignableTo', () {
var pokemonType = container.reflector.reflectType(Pokemon);
var kantoPokemonType = container.reflector.reflectType(KantoPokemon)!;
expect(kantoPokemonType.isAssignableTo(pokemonType), true);
expect(
kantoPokemonType
.isAssignableTo(container.reflector.reflectType(String)),
false);
});
}
class LowerPokemon {
final Pokemon pokemon;
LowerPokemon(this.pokemon);
String get lowercaseName => pokemon.name.toLowerCase();
}
class Pokemon {
final String name;
final PokemonType type;
Pokemon(this.name, this.type);
factory Pokemon.changeName(Pokemon other, String name) {
return Pokemon(name, other.type);
}
@override
String toString() => 'NAME: $name, TYPE: $type';
}
class KantoPokemon extends Pokemon {
KantoPokemon(super.name, super.type);
}
enum PokemonType { water, fire, grass, ice, poison, flying }

View file

@ -1,138 +0,0 @@
import 'package:platform_container/container.dart';
import 'package:test/test.dart';
void main() {
var reflector = const EmptyReflector();
test('getName', () {
expect(reflector.getName(#foo), 'foo');
expect(reflector.getName(#==), '==');
});
group('reflectClass', () {
var mirror = reflector.reflectClass(Truck);
test('name returns empty', () {
expect(mirror.name, '(empty)');
});
test('annotations returns empty', () {
expect(mirror.annotations, isEmpty);
});
test('typeParameters returns empty', () {
expect(mirror.typeParameters, isEmpty);
});
test('declarations returns empty', () {
expect(mirror.declarations, isEmpty);
});
test('constructors returns empty', () {
expect(mirror.constructors, isEmpty);
});
test('reflectedType returns Object', () {
expect(mirror.reflectedType, Object);
});
test('cannot call newInstance', () {
expect(() => mirror.newInstance('', []), throwsUnsupportedError);
});
test('isAssignableTo self', () {
expect(mirror.isAssignableTo(mirror), true);
});
});
group('reflectType', () {
var mirror = reflector.reflectType(Truck);
test('name returns empty', () {
expect(mirror.name, '(empty)');
});
test('typeParameters returns empty', () {
expect(mirror.typeParameters, isEmpty);
});
test('reflectedType returns Object', () {
expect(mirror.reflectedType, Object);
});
test('cannot call newInstance', () {
expect(() => mirror.newInstance('', []), throwsUnsupportedError);
});
test('isAssignableTo self', () {
expect(mirror.isAssignableTo(mirror), true);
});
});
group('reflectFunction', () {
void doIt(int x) {}
var mirror = reflector.reflectFunction(doIt);
test('name returns empty', () {
expect(mirror.name, '(empty)');
});
test('annotations returns empty', () {
expect(mirror.annotations, isEmpty);
});
test('typeParameters returns empty', () {
expect(mirror.typeParameters, isEmpty);
});
test('parameters returns empty', () {
expect(mirror.parameters, isEmpty);
});
test('return type is dynamic', () {
expect(mirror.returnType, reflector.reflectType(dynamic));
});
test('isGetter returns false', () {
expect(mirror.isGetter, false);
});
test('isSetter returns false', () {
expect(mirror.isSetter, false);
});
test('cannot invoke', () {
var invocation = Invocation.method(#drive, []);
expect(() => mirror.invoke(invocation), throwsUnsupportedError);
});
});
group('reflectInstance', () {
var mirror = reflector.reflectInstance(Truck());
test('reflectee returns null', () {
expect(mirror.reflectee, null);
});
test('type returns empty', () {
expect(mirror.type.name, '(empty)');
});
test('clazz returns empty', () {
expect(mirror.clazz.name, '(empty)');
});
test('cannot getField', () {
expect(() => mirror.getField('wheelCount'), throwsUnsupportedError);
});
});
}
class Truck {
int get wheelCount => 4;
void drive() {
print('Vroom!!!');
}
}

View file

@ -1,51 +0,0 @@
import 'package:platform_container/container.dart';
import 'package:test/test.dart';
void main() {
late Container container;
setUp(() {
container = Container(const EmptyReflector())
..registerSingleton<Song>(Song(title: 'I Wish'))
..registerNamedSingleton('foo', 1)
..registerFactory<Artist>((container) {
return Artist(
name: 'Stevie Wonder',
song: container.make<Song>(),
);
});
});
test('hasNamed', () {
var child = container.createChild()..registerNamedSingleton('bar', 2);
expect(child.hasNamed('foo'), true);
expect(child.hasNamed('bar'), true);
expect(child.hasNamed('baz'), false);
});
test('has on singleton', () {
var result = container.has<Song>();
expect(result, true);
});
test('has on factory', () {
expect(container.has<Artist>(), true);
});
test('false if neither', () {
expect(container.has<bool>(), false);
});
}
class Artist {
final String? name;
final Song? song;
Artist({this.name, this.song});
}
class Song {
final String? title;
Song({this.title});
}

View file

@ -1,18 +0,0 @@
import 'package:platform_container/container.dart';
import 'package:test/test.dart';
void main() {
test('returns the same instance', () {
var container = Container(const EmptyReflector())
..registerLazySingleton<Dummy>((_) => Dummy('a'));
var first = container.make<Dummy>();
expect(container.make<Dummy>(), first);
});
}
class Dummy {
final String s;
Dummy(this.s);
}

View file

@ -1,26 +0,0 @@
import 'dart:async';
import 'package:platform_container/container.dart';
import 'package:platform_container/mirrors.dart';
import 'package:test/test.dart';
import 'common.dart';
void main() {
testReflector(const MirrorsReflector());
test('futureOf', () {
var r = MirrorsReflector();
var fStr = r.reflectFutureOf(String);
expect(fStr.reflectedType.toString(), 'Future<String>');
// expect(fStr.reflectedType, Future<String>.value(null).runtimeType);
});
test('concrete future make', () async {
var c = Container(MirrorsReflector());
c.registerFactory<Future<String>>((_) async => 'hey');
var fStr = c.reflector.reflectFutureOf(String);
var s1 = await c.make(fStr.reflectedType);
var s2 = await c.makeAsync(String);
print([s1, s2]);
expect(s1, s2);
});
}

View file

@ -1,34 +0,0 @@
import 'package:platform_container/container.dart';
import 'package:test/test.dart';
void main() {
late Container container;
setUp(() {
container = Container(const EmptyReflector());
container.registerNamedSingleton('foo', Foo(bar: 'baz'));
});
test('fetch by name', () {
expect(container.findByName<Foo>('foo').bar, 'baz');
});
test('cannot redefine', () {
expect(() => container.registerNamedSingleton('foo', Foo(bar: 'quux')),
throwsStateError);
});
test('throws on unknown name', () {
expect(() => container.findByName('bar'), throwsStateError);
});
test('throws on incorrect type', () {
expect(() => container.findByName<List<String>>('foo'), throwsA(anything));
});
}
class Foo {
final String? bar;
Foo({this.bar});
}

View file

@ -1,36 +0,0 @@
import 'package:platform_container/container.dart';
import 'package:test/test.dart';
void main() {
var reflector = const ThrowingReflector();
test('getName', () {
expect(reflector.getName(#foo), 'foo');
expect(reflector.getName(#==), '==');
});
test('reflectClass fails', () {
expect(() => reflector.reflectClass(Truck), throwsUnsupportedError);
});
test('reflectType fails', () {
expect(() => reflector.reflectType(Truck), throwsUnsupportedError);
});
test('reflectFunction throws', () {
void doIt(int x) {}
expect(() => reflector.reflectFunction(doIt), throwsUnsupportedError);
});
test('reflectInstance throws', () {
expect(() => reflector.reflectInstance(Truck()), throwsUnsupportedError);
});
}
class Truck {
int get wheelCount => 4;
void drive() {
print('Vroom!!!');
}
}

View file

@ -1,16 +0,0 @@
# See https://www.dartlang.org/guides/libraries/private-files
# Files and directories created by pub
.dart_tool/
.packages
.pub/
build/
# If you're building an application, you may want to check-in your pubspec.lock
pubspec.lock
# Directory created by dartdoc
# If you don't generate documentation locally you can remove this line.
doc/api/
test/*.reflectable.dart
example/*.reflectable.dart

View file

@ -1,58 +0,0 @@
# Change Log
## 8.1.1
* Updated repository link
## 8.1.0
* Updated `lints` to 3.0.0
* Fixed analyser warnings
## 8.0.0
* Require Dart >= 3.0
## 7.1.0-beta.1
* Require Dart >= 2.19
* Upgraded `relectable` to 4.x.x
## 7.0.0
* Require Dart >= 2.17
## 6.0.0
* Require Dart >= 2.16
## 5.0.0
* Skipped release
## 4.0.0
* Skipped release
## 3.0.1
* Updated `package:angel3_container`
## 3.0.0
* Fixed NNBD issues
* All 9 test cases passed
## 3.0.0-beta.1
* Migrated to support Dart >= 2.12 NNBD
* Updated linter to `package:lints`
* Updated to use `platform_` packages
## 2.0.0
* Migrated to work with Dart >= 2.12 Non NNBD
## 1.0.1
* Update for `pkg:angel_container@1.0.3`.

View file

@ -1,29 +0,0 @@
BSD 3-Clause License
Copyright (c) 2021, dukefirehawk.com
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,32 +0,0 @@
# Protevus Container Generator
![Pub Version (including pre-releases)](https://img.shields.io/pub/v/angel3_container_generator?include_prereleases)
[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)
[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion)
[![License](https://img.shields.io/github/license/dart-backend/angel)](https://github.com/dart-backend/angel/tree/master/packages/container/angel3_container_generator/LICENSE)
An alternative container for Protevus that uses `reflectable` package instead of `dart:mirrors` for reflection. However, `reflectable` has more limited relfection capabilities when compared to `dart:mirrors`.
## Usage
* Annotable the class with `@contained`.
* Run `dart run build_runner build <Your class directory>`
* Alternatively create a `build.xml` file with the following content
```yaml
targets:
$default:
builders:
reflectable:
generate_for:
- bin/**_controller.dart
options:
formatted: true
```
## Known limitation
* `analyser` 6.x is not supported due to `reflectable`
* Reflection on functions/closures is not supported
* Reflection on private declarations is not supported
* Reflection on generic type is not supported

View file

@ -1 +0,0 @@
include: package:lints/recommended.yaml

View file

@ -1,75 +0,0 @@
import 'dart:async';
import 'package:platform_container/container.dart';
import 'package:platform_container_generator/generator.dart';
Future<void> main() async {
// Create a container instance.
Container container = Container(GeneratedReflector());
// Register a singleton.
container.registerSingleton<Engine>(Engine(40));
// You can also omit the type annotation, in which the object's runtime type will be used.
// If you're injecting an abstract class, prefer the type annotation.
//
// container.registerSingleton(Engine(40));
// Register a factory that creates a truck.
container.registerFactory<Truck>((container) {
return _TruckImpl(container.make<Engine>());
});
// Use `make` to create an instance.
var truck = container.make<Truck>();
// You can also resolve injections asynchronously.
container.registerFactory<Future<int>>((_) async => 24);
print(await container.makeAsync<int>());
// Asynchronous resolution also works for plain objects.
await container.makeAsync<Truck>().then((t) => t.drive());
// Register a named singleton.
container.registerNamedSingleton('the_truck', truck);
// Should print: 'Vroom! I have 40 horsepower in my engine.'
truck.drive();
// Should print the same.
container.findByName<Truck>('the_truck').drive();
// We can make a child container with its own factory.
var childContainer = container.createChild();
childContainer.registerFactory<Truck>((container) {
return _TruckImpl(Engine(5666));
});
// Make a truck with 5666 HP.
childContainer.make<Truck>().drive();
// However, calling `make<Engine>` will return the Engine singleton we created above.
print(childContainer.make<Engine>().horsePower);
}
abstract class Truck {
void drive();
}
class Engine {
final int horsePower;
Engine(this.horsePower);
}
class _TruckImpl implements Truck {
final Engine engine;
_TruckImpl(this.engine);
@override
void drive() {
print('Vroom! I have ${engine.horsePower} horsepower in my engine.');
}
}

View file

@ -1,255 +0,0 @@
import 'package:platform_container/container.dart';
import 'package:reflectable/reflectable.dart';
/// A [Reflectable] instance that can be used as an annotation on types to generate metadata for them.
const Reflectable contained = ContainedReflectable();
@contained
class ContainedReflectable extends Reflectable {
const ContainedReflectable()
: super(
topLevelInvokeCapability,
typeAnnotationQuantifyCapability,
superclassQuantifyCapability,
libraryCapability,
invokingCapability,
metadataCapability,
reflectedTypeCapability,
typeCapability,
typingCapability);
}
/// A [Reflector] instance that uses a [Reflectable] to reflect upon data.
class GeneratedReflector extends Reflector {
final Reflectable reflectable;
const GeneratedReflector([this.reflectable = contained]);
@override
String getName(Symbol symbol) {
return symbol.toString().substring(7);
}
@override
ReflectedClass reflectClass(Type clazz) {
return reflectType(clazz) as ReflectedClass;
}
@override
ReflectedFunction reflectFunction(Function function) {
if (!reflectable.canReflect(function)) {
throw UnsupportedError('Cannot reflect $function.');
}
var mirror = reflectable.reflect(function);
if (mirror is ClosureMirror) {
return _GeneratedReflectedFunction(mirror.function, this, mirror);
} else {
throw ArgumentError('$function is not a Function.');
}
}
@override
ReflectedInstance reflectInstance(Object object) {
if (!reflectable.canReflect(object)) {
throw UnsupportedError('Cannot reflect $object.');
} else {
var mirror = reflectable.reflect(object);
return _GeneratedReflectedInstance(mirror, this);
}
}
@override
ReflectedType reflectType(Type type) {
if (!reflectable.canReflectType(type)) {
throw UnsupportedError('Cannot reflect $type.');
} else {
var mirror = reflectable.reflectType(type);
return mirror is ClassMirror
? _GeneratedReflectedClass(mirror, this)
: _GeneratedReflectedType(mirror);
}
}
}
class _GeneratedReflectedInstance extends ReflectedInstance {
final InstanceMirror mirror;
final GeneratedReflector reflector;
_GeneratedReflectedInstance(this.mirror, this.reflector)
: super(_GeneratedReflectedType(mirror.type),
_GeneratedReflectedClass(mirror.type, reflector), mirror.reflectee);
@override
ReflectedType get type => clazz;
@override
ReflectedInstance getField(String name) {
var result = mirror.invokeGetter(name)!;
var instance = reflector.reflectable.reflect(result);
return _GeneratedReflectedInstance(instance, reflector);
}
}
class _GeneratedReflectedClass extends ReflectedClass {
final ClassMirror mirror;
final Reflector reflector;
_GeneratedReflectedClass(this.mirror, this.reflector)
: super(mirror.simpleName, [], [], [], [], mirror.reflectedType);
@override
List<ReflectedTypeParameter> get typeParameters =>
mirror.typeVariables.map(_convertTypeVariable).toList();
@override
List<ReflectedFunction> get constructors =>
_constructorsOf(mirror.declarations, reflector);
@override
List<ReflectedDeclaration> get declarations =>
_declarationsOf(mirror.declarations, reflector);
@override
List<ReflectedInstance> get annotations => mirror.metadata
.map(reflector.reflectInstance)
.whereType<ReflectedInstance>()
.toList();
@override
bool isAssignableTo(ReflectedType? other) {
if (other is _GeneratedReflectedClass) {
return mirror.isAssignableTo(other.mirror);
} else if (other is _GeneratedReflectedType) {
return mirror.isAssignableTo(other.mirror);
} else {
return false;
}
}
@override
ReflectedInstance newInstance(
String constructorName, List positionalArguments,
[Map<String, dynamic>? namedArguments, List<Type>? typeArguments]) {
namedArguments ??= {};
var result = mirror.newInstance(constructorName, positionalArguments,
namedArguments.map((k, v) => MapEntry(Symbol(k), v)));
return reflector.reflectInstance(result)!;
}
}
class _GeneratedReflectedType extends ReflectedType {
final TypeMirror mirror;
_GeneratedReflectedType(this.mirror)
: super(mirror.simpleName, [], mirror.reflectedType);
@override
List<ReflectedTypeParameter> get typeParameters =>
mirror.typeVariables.map(_convertTypeVariable).toList();
@override
bool isAssignableTo(ReflectedType? other) {
if (other is _GeneratedReflectedClass) {
return mirror.isAssignableTo(other.mirror);
} else if (other is _GeneratedReflectedType) {
return mirror.isAssignableTo(other.mirror);
} else {
return false;
}
}
@override
ReflectedInstance newInstance(
String constructorName, List positionalArguments,
[Map<String, dynamic> namedArguments = const {},
List<Type> typeArguments = const []]) {
throw UnsupportedError('Cannot create a new instance of $reflectedType.');
}
}
class _GeneratedReflectedFunction extends ReflectedFunction {
final MethodMirror mirror;
final Reflector reflector;
final ClosureMirror? closure;
_GeneratedReflectedFunction(this.mirror, this.reflector, [this.closure])
: super(
mirror.simpleName,
[],
[],
mirror.parameters
.map((p) => _convertParameter(p, reflector))
.toList(),
mirror.isGetter,
mirror.isSetter,
returnType: !mirror.isRegularMethod
? null
: _GeneratedReflectedType(mirror.returnType));
@override
List<ReflectedInstance> get annotations => mirror.metadata
.map(reflector.reflectInstance)
.whereType<ReflectedInstance>()
.toList();
@override
ReflectedInstance invoke(Invocation invocation) {
if (closure != null) {
throw UnsupportedError('Only closures can be invoked directly.');
} else {
var result = closure!.delegate(invocation)!;
return reflector.reflectInstance(result)!;
}
}
}
List<ReflectedFunction> _constructorsOf(
Map<String, DeclarationMirror> map, Reflector reflector) {
return map.entries.fold<List<ReflectedFunction>>([], (out, entry) {
var v = entry.value;
if (v is MethodMirror && v.isConstructor) {
return out..add(_GeneratedReflectedFunction(v, reflector));
} else {
return out;
}
});
}
List<ReflectedDeclaration> _declarationsOf(
Map<String, DeclarationMirror> map, Reflector reflector) {
return map.entries.fold<List<ReflectedDeclaration>>([], (out, entry) {
var v = entry.value;
if (v is VariableMirror) {
var decl = ReflectedDeclaration(v.simpleName, v.isStatic, null);
return out..add(decl);
}
if (v is MethodMirror) {
var decl = ReflectedDeclaration(
v.simpleName, v.isStatic, _GeneratedReflectedFunction(v, reflector));
return out..add(decl);
} else {
return out;
}
});
}
ReflectedTypeParameter _convertTypeVariable(TypeVariableMirror mirror) {
return ReflectedTypeParameter(mirror.simpleName);
}
ReflectedParameter _convertParameter(
ParameterMirror mirror, Reflector reflector) {
return ReflectedParameter(
mirror.simpleName,
mirror.metadata
.map(reflector.reflectInstance)
.whereType<ReflectedInstance>()
.toList(),
reflector.reflectType(mirror.type.reflectedType)!,
!mirror.isOptional,
mirror.isNamed);
}

View file

@ -1,19 +0,0 @@
name: platform_container_generator
version: 9.0.0
description: Protevus Platform Codegen support for using pkg:reflectable with pkg:platform_container.
homepage: https://protevus.com
documentation: https://docs.protevus.com
repository: https://git.protevus.com/protevus/platform/src/branch/main/packages/container/container_generator
environment:
sdk: '>=3.3.0 <4.0.0'
dependencies:
platform_container: ^9.0.0
reflectable: ^4.0.12
dev_dependencies:
build_runner: ^2.4.13
build_test: ^2.2.2
test: ^1.25.8
lints: ^4.0.0
# dependency_overrides:
# platform_container:
# path: ../platform_container

View file

@ -1,179 +0,0 @@
import 'package:platform_container/container.dart';
import 'package:platform_container_generator/generator.dart';
import 'package:test/test.dart';
import 'reflector_test.reflectable.dart';
void main() {
initializeReflectable();
var reflector = const GeneratedReflector();
late Container container;
setUp(() {
container = Container(reflector);
container.registerSingleton(Artist(name: 'Stevie Wonder'));
});
group('reflectClass', () {
var mirror = reflector.reflectClass(Artist);
test('name', () {
expect(mirror.name, 'Artist');
});
});
test('inject constructor parameters', () {
var album = container.make<Album>();
print(album.title);
expect(album.title, 'flowers by stevie wonder');
});
// Skip as pkg:reflectable cannot reflect on closures at all (yet)
//testReflector(reflector);
}
@contained
void returnVoidFromAFunction(int x) {}
void testReflector(Reflector reflector) {
var blaziken = Pokemon('Blaziken', PokemonType.fire);
late Container container;
setUp(() {
container = Container(reflector);
container.registerSingleton(blaziken);
});
test('get field', () {
var blazikenMirror = reflector.reflectInstance(blaziken)!;
expect(blazikenMirror.getField('type').reflectee, blaziken.type);
});
group('reflectFunction', () {
var mirror = reflector.reflectFunction(returnVoidFromAFunction);
test('void return type returns dynamic', () {
expect(mirror?.returnType, reflector.reflectType(dynamic));
});
test('counts parameters', () {
expect(mirror?.parameters, hasLength(1));
});
test('counts types parameters', () {
expect(mirror?.typeParameters, isEmpty);
});
test('correctly reflects parameter types', () {
var p = mirror?.parameters[0];
expect(p?.name, 'x');
expect(p?.isRequired, true);
expect(p?.isNamed, false);
expect(p?.annotations, isEmpty);
expect(p?.type, reflector.reflectType(int));
});
}, skip: 'pkg:reflectable cannot reflect on closures at all (yet)');
test('make on singleton type returns singleton', () {
expect(container.make(Pokemon), blaziken);
});
test('make with generic returns same as make with explicit type', () {
expect(container.make<Pokemon>(), blaziken);
});
test('make on aliased singleton returns singleton', () {
container.registerSingleton(blaziken, as: StateError);
expect(container.make(StateError), blaziken);
});
test('constructor injects singleton', () {
var lower = container.make<LowerPokemon>();
expect(lower.lowercaseName, blaziken.name.toLowerCase());
});
test('newInstance works', () {
var type = container.reflector.reflectType(Pokemon)!;
var instance =
type.newInstance('changeName', [blaziken, 'Charizard']).reflectee
as Pokemon;
print(instance);
expect(instance.name, 'Charizard');
expect(instance.type, PokemonType.fire);
});
test('isAssignableTo', () {
var pokemonType = container.reflector.reflectType(Pokemon);
var kantoPokemonType = container.reflector.reflectType(KantoPokemon)!;
expect(kantoPokemonType.isAssignableTo(pokemonType), true);
expect(
kantoPokemonType
.isAssignableTo(container.reflector.reflectType(String)),
false);
});
}
@contained
class LowerPokemon {
final Pokemon pokemon;
LowerPokemon(this.pokemon);
String get lowercaseName => pokemon.name.toLowerCase();
}
@contained
class Pokemon {
final String name;
final PokemonType type;
Pokemon(this.name, this.type);
factory Pokemon.changeName(Pokemon other, String name) {
return Pokemon(name, other.type);
}
@override
String toString() => 'NAME: $name, TYPE: $type';
}
@contained
class KantoPokemon extends Pokemon {
KantoPokemon(super.name, super.type);
}
@contained
enum PokemonType { water, fire, grass, ice, poison, flying }
@contained
class Artist {
final String name;
Artist({required this.name});
String get lowerName {
return name.toLowerCase();
}
}
@contained
class Album {
final Artist artist;
Album(this.artist);
String get title => 'flowers by ${artist.lowerName}';
}
@contained
class AlbumLength {
final Artist artist;
final Album album;
AlbumLength(this.artist, this.album);
int get totalLength => artist.name.length + album.title.length;
}

View file

@ -1,71 +0,0 @@
/// Platform Contracts Library
///
/// This library provides the core contracts (interfaces) that define
/// the Platform framework's API. These contracts ensure consistency
/// and interoperability between components while enabling loose coupling
/// and dependency injection.
// Level 0: Core Foundation Contracts
// Container contracts (from packages/container)
export 'src/container/container.dart';
// Reflection contracts (from packages/container)
export 'src/reflection/reflection.dart';
// Pipeline contracts (from packages/pipeline)
export 'src/pipeline/pipeline.dart';
// Level 1: Infrastructure Contracts
// Events contracts (from packages/events)
export 'src/events/events.dart';
// Bus contracts (from packages/bus)
export 'src/bus/bus.dart';
// Model contracts (from packages/model)
export 'src/model/model.dart';
// Process contracts (from packages/process)
export 'src/process/process.dart';
// Support contracts (from packages/support)
export 'src/support/support.dart';
// Level 2: Core Services Contracts
// Queue contracts (from packages/queue)
export 'src/queue/queue.dart';
// Level 3: HTTP Layer Contracts
// Routing contracts (from packages/route)
export 'src/routing/routing.dart';
// HTTP contracts (from packages/core)
export 'src/http/http.dart';
// Testing Contracts
// Testing contracts (from packages/testing)
export 'src/testing/testing.dart';
// All contracts have been extracted from implemented packages:
// - Container & Reflection (Level 0)
// - Pipeline (Level 0)
// - Events (Level 1)
// - Bus (Level 1)
// - Model (Level 1)
// - Process (Level 1)
// - Support (Level 1)
// - Queue (Level 2)
// - Route (Level 3)
// - HTTP (Level 3)
// - Testing
// Next steps:
// 1. Update package dependencies to use these contracts
// 2. Implement contracts in each package
// 3. Add contract compliance tests
// 4. Document contract usage and patterns

View file

@ -1,2 +0,0 @@
/// Bus package contracts
export 'bus_contract.dart';

View file

@ -1,196 +0,0 @@
import 'package:meta/meta.dart';
/// Contract for commands.
///
/// Laravel-compatible: Base interface for command objects that can be
/// dispatched through the command bus.
@sealed
abstract class CommandContract {}
/// Contract for queueable commands.
///
/// Laravel-compatible: Marks commands that should be processed
/// through the queue system.
@sealed
abstract class ShouldQueueCommand implements CommandContract {}
/// Contract for command handlers.
///
/// Laravel-compatible: Defines how command handlers should process
/// their associated commands, with platform-specific typing.
@sealed
abstract class HandlerContract {
/// Handles a command.
///
/// Laravel-compatible: Core handler method with platform-specific
/// return type for more flexibility.
///
/// Parameters:
/// - [command]: The command to handle.
Future<dynamic> handle(CommandContract command);
}
/// Type definition for command pipe functions.
///
/// Platform-specific: Defines transformation functions that can modify
/// commands as they flow through the pipeline.
typedef CommandPipe = CommandContract Function(CommandContract);
/// Contract for command dispatching.
///
/// This contract defines the core interface for dispatching
/// and processing commands through the command bus.
@sealed
abstract class CommandDispatcherContract {
/// Dispatches a command.
///
/// Laravel-compatible: Core dispatch method.
///
/// Parameters:
/// - [command]: The command to dispatch.
Future<dynamic> dispatch(CommandContract command);
/// Dispatches a command synchronously.
///
/// Platform-specific: Provides explicit sync dispatch with optional handler.
///
/// Parameters:
/// - [command]: The command to dispatch.
/// - [handler]: Optional specific handler.
Future<dynamic> dispatchSync(CommandContract command,
[HandlerContract? handler]);
/// Dispatches a command immediately.
///
/// Laravel-compatible: Immediate dispatch without queueing.
/// Extended with optional handler parameter.
///
/// Parameters:
/// - [command]: The command to dispatch.
/// - [handler]: Optional specific handler.
Future<dynamic> dispatchNow(CommandContract command,
[HandlerContract? handler]);
/// Dispatches a command to queue.
///
/// Laravel-compatible: Queue-based dispatch.
///
/// Parameters:
/// - [command]: The command to queue.
Future<dynamic> dispatchToQueue(CommandContract command);
/// Finds a command batch.
///
/// Platform-specific: Provides batch lookup functionality.
///
/// Parameters:
/// - [batchId]: The batch ID to find.
Future<CommandBatchContract?> findBatch(String batchId);
/// Creates a command batch.
///
/// Laravel-compatible: Creates command batches.
/// Extended with platform-specific batch contract.
///
/// Parameters:
/// - [commands]: Commands to include in batch.
PendingCommandBatchContract batch(List<CommandContract> commands);
/// Creates a command chain.
///
/// Laravel-compatible: Creates command chains.
/// Extended with platform-specific chain contract.
///
/// Parameters:
/// - [commands]: Commands to chain.
CommandChainContract chain(List<CommandContract> commands);
/// Maps command types to handlers.
///
/// Platform-specific: Provides explicit handler mapping.
///
/// Parameters:
/// - [handlers]: Map of command types to handler types.
CommandDispatcherContract map(Map<Type, Type> handlers);
/// Applies transformation pipes to commands.
///
/// Platform-specific: Adds pipeline transformation support.
///
/// Parameters:
/// - [pipes]: List of command transformation functions.
CommandDispatcherContract pipeThrough(List<CommandPipe> pipes);
/// Dispatches after current response.
///
/// Laravel-compatible: Delayed dispatch after response.
///
/// Parameters:
/// - [command]: Command to dispatch later.
void dispatchAfterResponse(CommandContract command);
}
/// Contract for command batches.
///
/// Laravel-compatible: Defines batch structure and operations.
/// Extended with additional status tracking.
@sealed
abstract class CommandBatchContract {
/// Gets the batch ID.
String get id;
/// Gets commands in the batch.
List<CommandContract> get commands;
/// Gets batch status.
///
/// Platform-specific: Provides detailed status tracking.
String get status;
/// Whether batch allows failures.
///
/// Laravel-compatible: Controls batch failure handling.
bool get allowsFailures;
/// Gets finished command count.
///
/// Platform-specific: Tracks completion progress.
int get finished;
/// Gets failed command count.
///
/// Platform-specific: Tracks failure count.
int get failed;
/// Gets pending command count.
///
/// Platform-specific: Tracks remaining commands.
int get pending;
}
/// Contract for pending command batches.
///
/// Laravel-compatible: Defines batch configuration and dispatch.
@sealed
abstract class PendingCommandBatchContract {
/// Allows failures in batch.
///
/// Laravel-compatible: Configures failure handling.
PendingCommandBatchContract allowFailures();
/// Dispatches the batch.
///
/// Laravel-compatible: Executes the batch.
Future<void> dispatch();
}
/// Contract for command chains.
///
/// Laravel-compatible: Defines sequential command execution.
@sealed
abstract class CommandChainContract {
/// Dispatches the chain.
///
/// Laravel-compatible: Executes commands in sequence.
Future<void> dispatch();
}

View file

@ -1,3 +0,0 @@
/// Container package contracts
export 'container_contract.dart';
export 'contextual_binding_contract.dart';

View file

@ -1,134 +0,0 @@
import 'package:meta/meta.dart';
import '../reflection/reflector_contract.dart';
/// Core container contract defining dependency injection functionality.
///
/// This contract defines the interface that all dependency injection containers
/// must implement. It provides methods for registering and resolving dependencies,
/// creating child containers, and managing named instances.
@sealed
abstract class ContainerContract {
/// Gets the reflector instance used by this container.
ReflectorContract get reflector;
/// Whether this is a root container (has no parent).
bool get isRoot;
/// Creates a child container that inherits from this container.
///
/// The child container can access all dependencies registered in its parent containers,
/// but can also define its own dependencies that override or extend the parent's.
/// This enables scoped dependency injection contexts.
ContainerContract createChild();
/// Checks if a type is registered in this container or its parents.
///
/// Parameters:
/// - [T]: The type to check for. If [T] is dynamic, [t] must be provided.
/// - [t]: Optional type parameter that overrides [T] if provided.
///
/// Returns true if the type is registered, false otherwise.
bool has<T>([Type? t]);
/// Checks if a named instance exists in this container or its parents.
///
/// Parameters:
/// - [name]: The name to check for.
///
/// Returns true if a named instance exists, false otherwise.
bool hasNamed(String name);
/// Makes an instance of type [T].
///
/// This will:
/// 1. Return a singleton if registered
/// 2. Create an instance via factory if registered
/// 3. Use reflection to create a new instance
///
/// Parameters:
/// - [type]: Optional type parameter that overrides [T] if provided.
///
/// Throws:
/// - ReflectionException if [T] is not a class or has no default constructor
T make<T>([Type? type]);
/// Makes an instance of type [T] asynchronously.
///
/// This will attempt to resolve a Future<T> in the following order:
/// 1. Wrap a synchronous [T] in Future
/// 2. Return a registered Future<T>
/// 3. Create a Future<T> via reflection
///
/// Parameters:
/// - [type]: Optional type parameter that overrides [T] if provided.
///
/// Throws:
/// - ReflectionException if no suitable injection is found
Future<T> makeAsync<T>([Type? type]);
/// Registers a singleton instance.
///
/// The instance will be shared across the container hierarchy.
///
/// Parameters:
/// - [object]: The singleton instance to register.
/// - [as]: Optional type to register the singleton as.
///
/// Returns the registered instance.
///
/// Throws:
/// - StateError if a singleton is already registered for the type
T registerSingleton<T>(T object, {Type? as});
/// Registers a factory function.
///
/// The factory will be called each time an instance is needed.
///
/// Parameters:
/// - [factory]: Function that creates instances.
/// - [as]: Optional type to register the factory as.
///
/// Returns the factory function.
///
/// Throws:
/// - StateError if a factory is already registered for the type
T Function(ContainerContract) registerFactory<T>(
T Function(ContainerContract) factory,
{Type? as});
/// Registers a lazy singleton.
///
/// The singleton will be created on first use.
///
/// Parameters:
/// - [factory]: Function that creates the singleton.
/// - [as]: Optional type to register the singleton as.
///
/// Returns the factory function.
T Function(ContainerContract) registerLazySingleton<T>(
T Function(ContainerContract) factory,
{Type? as});
/// Gets a named singleton.
///
/// Parameters:
/// - [name]: The name of the singleton to retrieve.
///
/// Returns the named singleton instance.
///
/// Throws:
/// - StateError if no singleton exists with the given name
T findByName<T>(String name);
/// Registers a named singleton.
///
/// Parameters:
/// - [name]: The name to register the singleton under.
/// - [object]: The singleton instance.
///
/// Returns the registered instance.
///
/// Throws:
/// - StateError if a singleton already exists with the given name
T registerNamedSingleton<T>(String name, T object);
}

View file

@ -1,42 +0,0 @@
import 'package:meta/meta.dart';
/// Contract for contextual binding in dependency injection.
///
/// This contract defines the interface for creating contextual bindings,
/// allowing dependencies to be resolved differently based on context.
@sealed
abstract class ContextualBindingContract {
/// Specifies the concrete type that triggers this contextual binding.
///
/// Parameters:
/// - [concrete]: The concrete type that needs dependencies.
///
/// Returns a builder for specifying what type is needed.
ContextualNeedsContract when(Type concrete);
}
/// Contract for specifying contextual needs.
///
/// This contract defines the interface for specifying what type
/// is needed in a particular context.
@sealed
abstract class ContextualNeedsContract {
/// Specifies the type needed in this context.
///
/// Returns a builder for specifying what to give.
ContextualGiveContract needs<T>();
}
/// Contract for specifying contextual implementations.
///
/// This contract defines the interface for specifying what
/// implementation to provide in a particular context.
@sealed
abstract class ContextualGiveContract {
/// Specifies what to give for this contextual binding.
///
/// Parameters:
/// - [implementation]: The implementation to provide.
/// This can be an instance, a factory function, or a type.
void give(dynamic implementation);
}

View file

@ -1,199 +0,0 @@
import 'package:meta/meta.dart';
/// Contract for event dispatching functionality.
///
/// This contract defines the interface for dispatching events,
/// managing listeners, and handling event broadcasting.
///
/// The contract includes both Laravel-compatible methods and platform-specific
/// extensions for enhanced functionality.
@sealed
abstract class EventDispatcherContract {
/// Registers an event listener.
///
/// Laravel-compatible: Registers event listeners, but with platform-specific
/// dynamic typing for more flexible event handling.
///
/// Parameters:
/// - [events]: Event type or list of event types to listen for.
/// - [listener]: Function to handle the event.
void listen(dynamic events, dynamic listener);
/// Checks if event has listeners.
///
/// Platform-specific: Provides listener existence checking.
///
/// Parameters:
/// - [eventName]: Name of the event to check.
bool hasListeners(String eventName);
/// Pushes an event for delayed processing.
///
/// Platform-specific: Supports delayed event processing.
///
/// Parameters:
/// - [event]: Name of the event.
/// - [payload]: Optional event payload.
void push(String event, [dynamic payload]);
/// Flushes delayed events.
///
/// Platform-specific: Processes delayed events immediately.
///
/// Parameters:
/// - [event]: Name of the event to flush.
Future<void> flush(String event);
/// Subscribes an event subscriber.
///
/// Laravel-compatible: Registers event subscribers, but with platform-specific
/// dynamic typing for more flexible subscription handling.
///
/// Parameters:
/// - [subscriber]: The subscriber to register.
void subscribe(dynamic subscriber);
/// Waits for an event to occur.
///
/// Platform-specific: Provides event waiting functionality.
///
/// Parameters:
/// - [event]: Event to wait for.
/// - [payload]: Optional payload to dispatch.
Future<dynamic> until(dynamic event, [dynamic payload]);
/// Dispatches an event.
///
/// Laravel-compatible: Dispatches events, with platform-specific
/// extensions for halting and payload handling.
///
/// Parameters:
/// - [event]: Event to dispatch.
/// - [payload]: Optional event payload.
/// - [halt]: Whether to halt after first handler.
Future<dynamic> dispatch(dynamic event, [dynamic payload, bool? halt]);
/// Gets registered listeners.
///
/// Laravel-compatible: Retrieves event listeners.
///
/// Parameters:
/// - [eventName]: Name of the event.
List<Function> getListeners(String eventName);
/// Removes an event listener.
///
/// Laravel-compatible: Removes event listeners.
///
/// Parameters:
/// - [event]: Event to remove listener for.
void forget(String event);
/// Removes pushed event listeners.
///
/// Platform-specific: Cleans up delayed event listeners.
void forgetPushed();
/// Sets queue resolver.
///
/// Laravel-compatible: Configures queue integration.
///
/// Parameters:
/// - [resolver]: Queue resolver function.
void setQueueResolver(Function resolver);
/// Sets transaction manager resolver.
///
/// Laravel-compatible: Configures transaction integration.
///
/// Parameters:
/// - [resolver]: Transaction manager resolver function.
void setTransactionManagerResolver(Function resolver);
/// Gets raw event listeners.
///
/// Platform-specific: Provides access to raw listener data.
Map<String, List<Function>> getRawListeners();
}
/// Contract for event subscribers.
///
/// Laravel-compatible: Defines how event subscribers register
/// their event handling methods.
@sealed
abstract class EventSubscriberContract {
/// Subscribes to events.
///
/// Laravel-compatible: Returns event handler mappings.
///
/// Returns a map of event types to handler functions.
Map<Type, Function> subscribe();
}
/// Marker interface for broadcastable events.
///
/// Laravel-compatible: Events implementing this interface will be broadcast
/// across the application.
@sealed
abstract class ShouldBroadcast {
/// Gets channels to broadcast on.
///
/// Laravel-compatible: Defines broadcast channels.
List<String> broadcastOn();
/// Gets event name for broadcasting.
///
/// Laravel-compatible: Defines broadcast event name.
String broadcastAs() => runtimeType.toString();
/// Gets broadcast data.
///
/// Laravel-compatible: Defines broadcast payload.
Map<String, dynamic> get broadcastWith => {};
}
/// Marker interface for queueable events.
///
/// Laravel-compatible: Events implementing this interface will be processed
/// through the queue system.
@sealed
abstract class ShouldQueue {
/// Gets the queue name.
///
/// Laravel-compatible: Defines target queue.
String get queue => 'default';
/// Gets the processing delay.
///
/// Laravel-compatible: Defines queue delay.
Duration? get delay => null;
/// Gets maximum retry attempts.
///
/// Laravel-compatible: Defines retry limit.
int get tries => 1;
}
/// Marker interface for encrypted events.
///
/// Laravel-compatible: Events implementing this interface will be encrypted
/// before being stored or transmitted.
@sealed
abstract class ShouldBeEncrypted {
/// Whether the event should be encrypted.
///
/// Laravel-compatible: Controls event encryption.
bool get shouldBeEncrypted => true;
}
/// Marker interface for events that should dispatch after commit.
///
/// Laravel-compatible: Events implementing this interface will only be dispatched
/// after the current database transaction commits.
@sealed
abstract class ShouldDispatchAfterCommit {
/// Whether to dispatch after commit.
///
/// Laravel-compatible: Controls transaction-based dispatch.
bool get afterCommit => true;
}

View file

@ -1,2 +0,0 @@
/// Events package contracts
export 'event_dispatcher_contract.dart';

View file

@ -1,2 +0,0 @@
/// HTTP package contracts
export 'http_contract.dart';

View file

@ -1,299 +0,0 @@
import 'package:meta/meta.dart';
/// Contract for HTTP requests.
///
/// Laravel-compatible: Core request functionality matching Laravel's Request
/// interface, with platform-specific stream handling.
@sealed
abstract class RequestContract {
/// Gets the request method.
///
/// Laravel-compatible: HTTP method accessor.
String get method;
/// Gets the request URI.
///
/// Laravel-compatible: Request URI using Dart's Uri class.
Uri get uri;
/// Gets request headers.
///
/// Laravel-compatible: Header access with platform-specific
/// multi-value support.
Map<String, List<String>> get headers;
/// Gets query parameters.
///
/// Laravel-compatible: Query parameter access.
Map<String, String> get query;
/// Gets POST data.
///
/// Laravel-compatible: POST data access.
Map<String, dynamic> get post;
/// Gets cookies.
///
/// Laravel-compatible: Cookie access.
Map<String, String> get cookies;
/// Gets uploaded files.
///
/// Laravel-compatible: File upload handling with
/// platform-specific contract.
Map<String, UploadedFileContract> get files;
/// Gets the request body.
///
/// Platform-specific: Stream-based body access.
Stream<List<int>> get body;
/// Gets a request header.
///
/// Laravel-compatible: Single header access.
String? header(String name, [String? defaultValue]);
/// Gets a query parameter.
///
/// Laravel-compatible: Single query parameter access.
String? query_(String name, [String? defaultValue]);
/// Gets a POST value.
///
/// Laravel-compatible: Single POST value access.
dynamic post_(String name, [dynamic defaultValue]);
/// Gets a cookie value.
///
/// Laravel-compatible: Single cookie access.
String? cookie(String name, [String? defaultValue]);
/// Gets an uploaded file.
///
/// Laravel-compatible: Single file access.
UploadedFileContract? file(String name);
/// Gets all input data (query + post).
///
/// Laravel-compatible: Combined input access.
Map<String, dynamic> all();
/// Gets input value from any source.
///
/// Laravel-compatible: Universal input access.
dynamic input(String name, [dynamic defaultValue]);
/// Checks if input exists.
///
/// Laravel-compatible: Input existence check.
bool has(String name);
/// Gets the raw request body as string.
///
/// Platform-specific: Async text body access.
Future<String> text();
/// Gets the request body as JSON.
///
/// Platform-specific: Async JSON body access.
Future<dynamic> json();
}
/// Contract for HTTP responses.
///
/// Laravel-compatible: Core response functionality matching Laravel's Response
/// interface, with platform-specific async features.
@sealed
abstract class ResponseContract {
/// Gets response headers.
///
/// Laravel-compatible: Header access with platform-specific
/// multi-value support.
Map<String, List<String>> get headers;
/// Gets the status code.
///
/// Laravel-compatible: Status code accessor.
int get status;
/// Sets the status code.
///
/// Laravel-compatible: Status code mutator.
set status(int value);
/// Sets a response header.
///
/// Laravel-compatible: Single header setting.
void header(String name, String value);
/// Sets multiple headers.
///
/// Laravel-compatible: Bulk header setting.
void headers_(Map<String, String> headers);
/// Sets a cookie.
///
/// Laravel-compatible: Cookie setting with platform-specific
/// security options.
void cookie(
String name,
String value, {
Duration? maxAge,
DateTime? expires,
String? domain,
String? path,
bool secure = false,
bool httpOnly = false,
String? sameSite,
});
/// Writes response body content.
///
/// Laravel-compatible: Content writing.
void write(dynamic content);
/// Sends JSON response.
///
/// Laravel-compatible: JSON response.
void json(dynamic data);
/// Sends file download.
///
/// Laravel-compatible: File download with platform-specific
/// async handling.
Future<void> download(String path, [String? name]);
/// Redirects to another URL.
///
/// Laravel-compatible: Redirect response.
void redirect(String url, [int status = 302]);
/// Sends the response.
///
/// Platform-specific: Async response sending.
Future<void> send();
}
/// Contract for uploaded files.
///
/// Laravel-compatible: File upload handling matching Laravel's UploadedFile
/// interface, with platform-specific async operations.
@sealed
abstract class UploadedFileContract {
/// Gets the original client filename.
///
/// Laravel-compatible: Original filename.
String get filename;
/// Gets the file MIME type.
///
/// Laravel-compatible: MIME type.
String get mimeType;
/// Gets the file size in bytes.
///
/// Laravel-compatible: File size.
int get size;
/// Gets temporary file path.
///
/// Laravel-compatible: Temporary storage.
String get path;
/// Moves file to new location.
///
/// Laravel-compatible: File movement with platform-specific
/// async handling.
Future<void> moveTo(String path);
/// Gets file contents as bytes.
///
/// Platform-specific: Async binary content access.
Future<List<int>> bytes();
/// Gets file contents as string.
///
/// Platform-specific: Async text content access.
Future<String> text();
}
/// Contract for HTTP middleware.
///
/// Laravel-compatible: Middleware functionality matching Laravel's Middleware
/// interface, with platform-specific async handling.
@sealed
abstract class MiddlewareContract {
/// Handles the request.
///
/// Laravel-compatible: Middleware handling with platform-specific
/// async processing.
///
/// Parameters:
/// - [request]: The incoming request.
/// - [next]: Function to pass to next middleware.
Future<ResponseContract> handle(RequestContract request,
Future<ResponseContract> Function(RequestContract) next);
}
/// Contract for HTTP kernel.
///
/// Laravel-compatible: HTTP kernel functionality matching Laravel's HttpKernel
/// interface, with platform-specific async processing.
@sealed
abstract class HttpKernelContract {
/// Gets global middleware.
///
/// Laravel-compatible: Global middleware list.
List<MiddlewareContract> get middleware;
/// Gets middleware groups.
///
/// Laravel-compatible: Middleware grouping.
Map<String, List<MiddlewareContract>> get middlewareGroups;
/// Gets route middleware.
///
/// Laravel-compatible: Route middleware mapping.
Map<String, MiddlewareContract> get routeMiddleware;
/// Handles an HTTP request.
///
/// Laravel-compatible: Request handling with platform-specific
/// async processing.
Future<ResponseContract> handle(RequestContract request);
/// Terminates the request/response cycle.
///
/// Laravel-compatible: Request termination with platform-specific
/// async processing.
Future<ResponseContract> terminate(
RequestContract request, ResponseContract response);
}
/// Contract for HTTP context.
///
/// Platform-specific: Provides request context beyond Laravel's
/// standard request handling.
@sealed
abstract class HttpContextContract {
/// Gets the current request.
RequestContract get request;
/// Gets the current response.
ResponseContract get response;
/// Gets context attributes.
Map<String, dynamic> get attributes;
/// Gets a context attribute.
T? getAttribute<T>(String key);
/// Sets a context attribute.
void setAttribute(String key, dynamic value);
/// Gets the route parameters.
Map<String, dynamic> get routeParams;
/// Gets a route parameter.
T? getRouteParam<T>(String name);
}

View file

@ -1,2 +0,0 @@
/// Model package contracts
export 'model_contract.dart';

View file

@ -1,148 +0,0 @@
import 'package:meta/meta.dart';
/// Contract for base model functionality.
///
/// Laravel-compatible: Provides core model functionality similar to Laravel's
/// Model class, adapted for Dart's type system and patterns.
@sealed
abstract class ModelContract {
/// Gets the model's unique identifier.
///
/// Laravel-compatible: Primary key accessor.
/// Extended with nullable String type for flexibility.
String? get id;
/// Sets the model's unique identifier.
///
/// Laravel-compatible: Primary key mutator.
/// Extended with nullable String type for flexibility.
set id(String? value);
/// Gets the creation timestamp.
///
/// Laravel-compatible: Created at timestamp accessor.
/// Uses Dart's DateTime instead of Carbon.
DateTime? get createdAt;
/// Sets the creation timestamp.
///
/// Laravel-compatible: Created at timestamp mutator.
/// Uses Dart's DateTime instead of Carbon.
set createdAt(DateTime? value);
/// Gets the last update timestamp.
///
/// Laravel-compatible: Updated at timestamp accessor.
/// Uses Dart's DateTime instead of Carbon.
DateTime? get updatedAt;
/// Sets the last update timestamp.
///
/// Laravel-compatible: Updated at timestamp mutator.
/// Uses Dart's DateTime instead of Carbon.
set updatedAt(DateTime? value);
/// Gets the ID as an integer.
///
/// Platform-specific: Provides integer ID conversion.
/// Returns -1 if ID is null or not a valid integer.
int get idAsInt;
/// Gets the ID as a string.
///
/// Platform-specific: Provides string ID conversion.
/// Returns empty string if ID is null.
String get idAsString;
}
/// Contract for auditable model functionality.
///
/// Laravel-compatible: Similar to Laravel's auditable trait,
/// providing user tracking for model changes.
@sealed
abstract class AuditableModelContract extends ModelContract {
/// Gets the ID of user who created the record.
///
/// Laravel-compatible: Created by user tracking.
/// Uses String ID instead of user model reference.
String? get createdBy;
/// Sets the ID of user who created the record.
///
/// Laravel-compatible: Created by user tracking.
/// Uses String ID instead of user model reference.
set createdBy(String? value);
/// Gets the ID of user who last updated the record.
///
/// Laravel-compatible: Updated by user tracking.
/// Uses String ID instead of user model reference.
String? get updatedBy;
/// Sets the ID of user who last updated the record.
///
/// Laravel-compatible: Updated by user tracking.
/// Uses String ID instead of user model reference.
set updatedBy(String? value);
}
/// Optional contract for model serialization.
///
/// Laravel-compatible: Similar to Laravel's serialization features,
/// adapted for Dart's type system.
@sealed
abstract class SerializableModelContract {
/// Converts model to a map.
///
/// Laravel-compatible: Similar to toArray() method.
Map<String, dynamic> toMap();
/// Creates model from a map.
///
/// Laravel-compatible: Similar to fill() method.
void fromMap(Map<String, dynamic> map);
}
/// Optional contract for model validation.
///
/// Platform-specific: Provides built-in validation support,
/// inspired by Laravel's validation but adapted for Dart.
@sealed
abstract class ValidatableModelContract {
/// Validates the model.
///
/// Platform-specific: Returns validation errors if invalid.
Map<String, List<String>>? validate();
/// Gets validation rules.
///
/// Platform-specific: Defines validation rules.
Map<String, List<String>> get rules;
/// Gets custom error messages.
///
/// Platform-specific: Defines custom validation messages.
Map<String, String> get messages;
}
/// Optional contract for model events.
///
/// Laravel-compatible: Similar to Laravel's model events,
/// adapted for Dart's event system.
@sealed
abstract class ObservableModelContract {
/// Gets the event name.
///
/// Laravel-compatible: Defines event identifier.
String get eventName;
/// Gets the event timestamp.
///
/// Platform-specific: Adds timestamp tracking to events.
DateTime get eventTimestamp;
/// Gets event data.
///
/// Laravel-compatible: Provides event payload.
Map<String, dynamic> get eventData;
}

View file

@ -1,2 +0,0 @@
/// Pipeline package contracts
export 'pipeline_contract.dart';

View file

@ -1,127 +0,0 @@
import 'package:meta/meta.dart';
/// Contract for a pipe that processes objects in a pipeline.
///
/// Laravel-compatible: Core pipe functionality matching Laravel's
/// pipe interface, with platform-specific async handling.
@sealed
abstract class PipeContract {
/// Handles the passable object.
///
/// Laravel-compatible: Core pipe handling with platform-specific
/// async processing.
///
/// Parameters:
/// - [passable]: The object being passed through the pipeline.
/// - [next]: Function to pass the object to the next pipe.
///
/// Returns the processed object, possibly modified.
Future<dynamic> handle(
dynamic passable, Future<dynamic> Function(dynamic) next);
}
/// Contract for a pipeline that processes objects through a series of pipes.
///
/// Laravel-compatible: Core pipeline functionality matching Laravel's
/// Pipeline class, with platform-specific fluent interface.
@sealed
abstract class PipelineContract {
/// Sets the object to be passed through the pipeline.
///
/// Laravel-compatible: Pipeline input setting.
///
/// Parameters:
/// - [passable]: The object to process.
///
/// Returns the pipeline instance for fluent chaining.
PipelineContract send(dynamic passable);
/// Sets the array of pipes to process the object through.
///
/// Laravel-compatible: Pipe configuration with platform-specific
/// flexibility for pipe types.
///
/// Parameters:
/// - [pipes]: The pipes to process the object through.
/// Can be a single pipe or an iterable of pipes.
///
/// Returns the pipeline instance for fluent chaining.
PipelineContract through(dynamic pipes);
/// Adds additional pipes to the pipeline.
///
/// Platform-specific: Additional method for pipe configuration
/// following Laravel's fluent pattern.
///
/// Parameters:
/// - [pipes]: The pipes to add.
/// Can be a single pipe or an iterable of pipes.
///
/// Returns the pipeline instance for fluent chaining.
PipelineContract pipe(dynamic pipes);
/// Sets the method to call on the pipes.
///
/// Laravel-compatible: Method name configuration.
///
/// Parameters:
/// - [method]: The name of the method to call.
///
/// Returns the pipeline instance for fluent chaining.
PipelineContract via(String method);
/// Runs the pipeline with a final destination callback.
///
/// Laravel-compatible: Pipeline execution with platform-specific
/// async processing.
///
/// Parameters:
/// - [destination]: Function to process the final result.
///
/// Returns the processed result.
Future<dynamic> then(dynamic Function(dynamic) destination);
/// Runs the pipeline and returns the result.
///
/// Platform-specific: Direct result access following Laravel's
/// pipeline execution pattern.
///
/// Returns the processed object directly.
Future<dynamic> thenReturn();
}
/// Contract for a pipeline hub that manages multiple pipelines.
///
/// Laravel-compatible: Pipeline management functionality matching
/// Laravel's pipeline hub features.
@sealed
abstract class PipelineHubContract {
/// Gets or creates a pipeline with the given name.
///
/// Laravel-compatible: Named pipeline access.
///
/// Parameters:
/// - [name]: The name of the pipeline.
///
/// Returns the pipeline instance.
PipelineContract pipeline(String name);
/// Sets the default pipes for a pipeline.
///
/// Laravel-compatible: Default pipe configuration.
///
/// Parameters:
/// - [name]: The name of the pipeline.
/// - [pipes]: The default pipes for the pipeline.
void defaults(String name, List<dynamic> pipes);
/// Registers a pipe type with a name.
///
/// Platform-specific: Named pipe type registration following
/// Laravel's service registration pattern.
///
/// Parameters:
/// - [name]: The name to register the pipe type under.
/// - [type]: The pipe type to register.
void registerPipeType(String name, Type type);
}

View file

@ -1,2 +0,0 @@
/// Process package contracts
export 'process_contract.dart';

View file

@ -1,251 +0,0 @@
import 'dart:async';
import 'dart:io';
import 'package:meta/meta.dart';
/// Contract for process management.
///
/// Platform-specific: Provides system process management following Laravel's
/// architectural patterns for resource management and lifecycle control.
@sealed
abstract class ProcessManagerContract {
/// Starts a new process.
///
/// Platform-specific: Creates and starts a new system process with
/// Laravel-style identifier and configuration options.
///
/// Parameters:
/// - [id]: Unique identifier for the process.
/// - [command]: Command to execute.
/// - [arguments]: Command arguments.
/// - [workingDirectory]: Optional working directory.
/// - [environment]: Optional environment variables.
/// - [timeout]: Optional execution timeout.
/// - [tty]: Whether to run in a terminal.
/// - [enableReadError]: Whether to enable error stream reading.
Future<ProcessContract> start(
String id,
String command,
List<String> arguments, {
String? workingDirectory,
Map<String, String>? environment,
Duration? timeout,
bool tty = false,
bool enableReadError = true,
});
/// Gets a running process by ID.
///
/// Platform-specific: Retrieves process by identifier,
/// following Laravel's repository pattern.
ProcessContract? get(String id);
/// Kills a process.
///
/// Platform-specific: Terminates a process with optional signal,
/// following Laravel's resource cleanup patterns.
///
/// Parameters:
/// - [id]: Process ID to kill.
/// - [signal]: Signal to send (default: SIGTERM).
Future<void> kill(String id, {ProcessSignal signal = ProcessSignal.sigterm});
/// Kills all managed processes.
///
/// Platform-specific: Bulk process termination,
/// following Laravel's collection operation patterns.
Future<void> killAll({ProcessSignal signal = ProcessSignal.sigterm});
/// Gets process events stream.
///
/// Platform-specific: Event streaming following Laravel's
/// event broadcasting patterns.
Stream<ProcessEventContract> get events;
/// Runs processes in a pool.
///
/// Platform-specific: Concurrent process execution following
/// Laravel's job queue worker pool patterns.
///
/// Parameters:
/// - [processes]: Processes to run.
/// - [concurrency]: Max concurrent processes.
Future<List<ProcessResultContract>> pool(
List<ProcessContract> processes, {
int concurrency = 5,
});
/// Runs processes in a pipeline.
///
/// Platform-specific: Sequential process execution following
/// Laravel's pipeline pattern.
Future<ProcessResultContract> pipeline(List<ProcessContract> processes);
/// Disposes the manager and all processes.
///
/// Platform-specific: Resource cleanup following Laravel's
/// service provider cleanup patterns.
void dispose();
}
/// Contract for process instances.
///
/// Platform-specific: Defines individual process behavior following
/// Laravel's resource management patterns.
@sealed
abstract class ProcessContract {
/// Gets the process command.
String get command;
/// Gets the process ID.
int? get pid;
/// Gets process start time.
DateTime? get startTime;
/// Gets process end time.
DateTime? get endTime;
/// Gets process output stream.
Stream<List<int>> get output;
/// Gets process error stream.
Stream<List<int>> get errorOutput;
/// Gets process exit code.
Future<int> get exitCode;
/// Whether the process is running.
bool get isRunning;
/// Starts the process.
Future<ProcessContract> start();
/// Runs the process to completion.
Future<ProcessResultContract> run();
/// Runs the process with a timeout.
///
/// Parameters:
/// - [timeout]: Maximum execution time.
///
/// Throws TimeoutException if process exceeds timeout.
Future<ProcessResultContract> runWithTimeout(Duration timeout);
/// Writes input to the process.
Future<void> write(String input);
/// Writes multiple lines to the process.
Future<void> writeLines(List<String> lines);
/// Kills the process.
Future<void> kill({ProcessSignal signal = ProcessSignal.sigterm});
/// Sends a signal to the process.
bool sendSignal(ProcessSignal signal);
/// Gets process output as string.
Future<String> get outputAsString;
/// Gets process error output as string.
Future<String> get errorOutputAsString;
/// Disposes the process.
Future<void> dispose();
}
/// Contract for process results.
///
/// Platform-specific: Defines process execution results following
/// Laravel's response/result patterns.
@sealed
abstract class ProcessResultContract {
/// Gets the process ID.
int get pid;
/// Gets the exit code.
int get exitCode;
/// Gets the process output.
String get output;
/// Gets the process error output.
String get errorOutput;
/// Gets string representation.
@override
String toString() {
return 'ProcessResult(pid: $pid, exitCode: $exitCode, output: ${output.length} chars, errorOutput: ${errorOutput.length} chars)';
}
}
/// Contract for process events.
///
/// Platform-specific: Defines process lifecycle events following
/// Laravel's event system patterns.
@sealed
abstract class ProcessEventContract {
/// Gets the process ID.
String get id;
/// Gets the event timestamp.
DateTime get timestamp;
}
/// Contract for process started events.
///
/// Platform-specific: Defines process start event following
/// Laravel's event naming and structure patterns.
@sealed
abstract class ProcessStartedEventContract extends ProcessEventContract {
/// Gets the started process.
ProcessContract get process;
@override
String toString() =>
'ProcessStartedEvent(id: $id, command: ${process.command})';
}
/// Contract for process exited events.
///
/// Platform-specific: Defines process exit event following
/// Laravel's event naming and structure patterns.
@sealed
abstract class ProcessExitedEventContract extends ProcessEventContract {
/// Gets the exit code.
int get exitCode;
@override
String toString() => 'ProcessExitedEvent(id: $id, exitCode: $exitCode)';
}
/// Contract for process pools.
///
/// Platform-specific: Defines concurrent process execution following
/// Laravel's worker pool patterns.
@sealed
abstract class ProcessPoolContract {
/// Gets maximum concurrent processes.
int get concurrency;
/// Gets active processes.
List<ProcessContract> get active;
/// Gets pending processes.
List<ProcessContract> get pending;
/// Runs processes in the pool.
Future<List<ProcessResultContract>> run(List<ProcessContract> processes);
}
/// Contract for process pipelines.
///
/// Platform-specific: Defines sequential process execution following
/// Laravel's pipeline pattern.
@sealed
abstract class ProcessPipelineContract {
/// Gets pipeline processes.
List<ProcessContract> get processes;
/// Runs the pipeline.
Future<ProcessResultContract> run();
}

View file

@ -1,2 +0,0 @@
/// Queue package contracts
export 'queue_contract.dart';

View file

@ -1,284 +0,0 @@
import 'package:meta/meta.dart';
/// Contract for queue operations.
///
/// Laravel-compatible: Core queue functionality matching Laravel's Queue
/// interface, adapted for Dart's type system and async patterns.
@sealed
abstract class QueueContract {
/// Pushes a job onto the queue.
///
/// Laravel-compatible: Core push method.
/// Uses dynamic job type for flexibility.
Future<String> push(dynamic job, [String? queue]);
/// Pushes a job onto a specific queue.
///
/// Laravel-compatible: Queue-specific push.
/// Uses dynamic job type for flexibility.
Future<String> pushOn(String queue, dynamic job);
/// Pushes a delayed job onto the queue.
///
/// Laravel-compatible: Delayed job push.
/// Uses Duration instead of DateTime/Carbon.
Future<String> later(Duration delay, dynamic job, [String? queue]);
/// Pushes a delayed job onto a specific queue.
///
/// Laravel-compatible: Queue-specific delayed push.
/// Uses Duration instead of DateTime/Carbon.
Future<String> laterOn(String queue, Duration delay, dynamic job);
/// Pushes multiple jobs onto the queue.
///
/// Laravel-compatible: Bulk job push.
/// Uses dynamic job type for flexibility.
Future<void> bulk(List<dynamic> jobs, [String? queue]);
/// Gets the next job from the queue.
///
/// Laravel-compatible: Job pop operation.
Future<JobContract?> pop([String? queue]);
/// Creates a job batch.
///
/// Laravel-compatible: Batch creation.
BatchContract batch(List<JobContract> jobs);
/// Gets a queue connection.
///
/// Laravel-compatible: Connection retrieval.
QueueConnectionContract connection([String? name]);
}
/// Contract for queue jobs.
///
/// Laravel-compatible: Core job interface matching Laravel's Job
/// contract, with platform-specific extensions.
@sealed
abstract class JobContract {
/// Gets the job ID.
///
/// Laravel-compatible: Job identifier.
String get id;
/// Gets the job payload.
///
/// Laravel-compatible: Job data.
Map<String, dynamic> get payload;
/// Gets the number of attempts.
///
/// Laravel-compatible: Attempt tracking.
int get attempts;
/// Gets the maximum number of tries.
///
/// Laravel-compatible: Retry limit.
int get tries;
/// Gets the job timeout in seconds.
///
/// Laravel-compatible: Timeout configuration.
int get timeout;
/// Gets the queue name.
///
/// Laravel-compatible: Queue designation.
String? get queue;
/// Gets the job delay.
///
/// Laravel-compatible: Delay configuration.
/// Uses Duration instead of DateTime/Carbon.
Duration? get delay;
/// Whether the job should be encrypted.
///
/// Platform-specific: Adds encryption support.
bool get shouldBeEncrypted;
/// Whether to dispatch after commit.
///
/// Laravel-compatible: Transaction support.
bool get afterCommit;
/// Executes the job.
///
/// Laravel-compatible: Core job execution.
Future<void> handle();
/// Handles job failure.
///
/// Laravel-compatible: Failure handling.
Future<void> failed([Exception? exception]);
/// Releases the job back to the queue.
///
/// Laravel-compatible: Job release.
/// Uses Duration instead of DateTime/Carbon.
Future<void> release([Duration? delay]);
/// Deletes the job.
///
/// Laravel-compatible: Job deletion.
Future<void> delete();
}
/// Contract for job batches.
///
/// Laravel-compatible: Batch operations matching Laravel's batch
/// functionality, with platform-specific extensions.
@sealed
abstract class BatchContract {
/// Gets the batch ID.
///
/// Laravel-compatible: Batch identifier.
String get id;
/// Gets the jobs in the batch.
///
/// Laravel-compatible: Batch jobs.
List<JobContract> get jobs;
/// Adds jobs to the batch.
///
/// Laravel-compatible: Job addition.
void add(List<JobContract> jobs);
/// Dispatches the batch.
///
/// Laravel-compatible: Batch dispatch.
Future<void> dispatch();
/// Allows failures in the batch.
///
/// Laravel-compatible: Failure configuration.
BatchContract allowFailures();
/// Sets the batch name.
///
/// Laravel-compatible: Batch naming.
BatchContract name(String name);
/// Adds a callback when all jobs finish.
///
/// Laravel-compatible: Success callback.
BatchContract then(void Function(BatchContract) callback);
/// Adds a callback when the batch fails.
///
/// Laravel-compatible: Error callback.
BatchContract onError(void Function(BatchContract, dynamic) callback);
/// Gets the batch progress.
///
/// Platform-specific: Progress tracking.
double get progress;
/// Gets finished job count.
///
/// Platform-specific: Completion tracking.
int get finished;
/// Gets failed job count.
///
/// Platform-specific: Failure tracking.
int get failed;
/// Gets pending job count.
///
/// Platform-specific: Pending tracking.
int get pending;
/// Gets total job count.
///
/// Platform-specific: Size tracking.
int get total;
}
/// Contract for queue connections.
///
/// Laravel-compatible: Connection management matching Laravel's
/// queue connection functionality.
@sealed
abstract class QueueConnectionContract {
/// Gets the connection name.
///
/// Laravel-compatible: Connection identifier.
String get name;
/// Gets the connection driver.
///
/// Laravel-compatible: Driver type.
String get driver;
/// Gets the connection config.
///
/// Laravel-compatible: Configuration access.
Map<String, dynamic> get config;
/// Pushes a job onto the queue.
///
/// Laravel-compatible: Job push.
Future<String> push(dynamic job, [String? queue]);
/// Gets the next job from the queue.
///
/// Laravel-compatible: Job pop.
Future<JobContract?> pop([String? queue]);
/// Gets queue size.
///
/// Laravel-compatible: Size check.
Future<int> size([String? queue]);
/// Clears the queue.
///
/// Laravel-compatible: Queue clear.
Future<void> clear([String? queue]);
/// Pauses job processing.
///
/// Laravel-compatible: Processing pause.
Future<void> pause([String? queue]);
/// Resumes job processing.
///
/// Laravel-compatible: Processing resume.
Future<void> resume([String? queue]);
}
/// Contract for queue manager.
///
/// Laravel-compatible: Manager functionality matching Laravel's
/// queue manager interface.
@sealed
abstract class QueueManagerContract {
/// Gets a queue connection.
///
/// Laravel-compatible: Connection retrieval.
QueueConnectionContract connection([String? name]);
/// Gets the default connection name.
///
/// Laravel-compatible: Default connection.
String get defaultConnection;
/// Sets the default connection name.
///
/// Laravel-compatible: Default connection.
set defaultConnection(String name);
/// Gets connection configuration.
///
/// Laravel-compatible: Config access.
Map<String, dynamic> getConfig(String name);
/// Extends available drivers.
///
/// Laravel-compatible: Driver extension.
void extend(String driver,
QueueConnectionContract Function(Map<String, dynamic>) callback);
}

View file

@ -1,2 +0,0 @@
/// Reflection package contracts
export 'reflector_contract.dart';

View file

@ -1,148 +0,0 @@
import 'package:meta/meta.dart';
/// Contract for reflected type parameters
@sealed
abstract class ReflectedTypeParameterContract {
/// Gets the name of the type parameter
String get name;
}
/// Contract for reflected types
@sealed
abstract class ReflectedTypeContract {
/// Gets the name of the type
String get name;
/// Gets the type parameters if the type is generic
List<ReflectedTypeParameterContract> get typeParameters;
/// Gets the actual Dart type being reflected
Type get reflectedType;
/// Checks if this type is assignable to another type
bool isAssignableTo(ReflectedTypeContract? other);
/// Creates a new instance of this type
ReflectedInstanceContract newInstance(
String constructorName, List positionalArguments,
[Map<String, dynamic> namedArguments = const {},
List<Type> typeArguments = const []]);
}
/// Contract for reflected parameters
@sealed
abstract class ReflectedParameterContract {
/// Gets the parameter name
String get name;
/// Gets the parameter annotations
List<ReflectedInstanceContract> get annotations;
/// Gets the parameter type
ReflectedTypeContract get type;
/// Whether the parameter is required
bool get isRequired;
/// Whether the parameter is named
bool get isNamed;
}
/// Contract for reflected functions
@sealed
abstract class ReflectedFunctionContract {
/// Gets the function name
String get name;
/// Gets the function's type parameters
List<ReflectedTypeParameterContract> get typeParameters;
/// Gets the function's annotations
List<ReflectedInstanceContract> get annotations;
/// Gets the function's return type
ReflectedTypeContract? get returnType;
/// Gets the function's parameters
List<ReflectedParameterContract> get parameters;
/// Whether the function is a getter
bool get isGetter;
/// Whether the function is a setter
bool get isSetter;
/// Invokes the function
ReflectedInstanceContract invoke(Invocation invocation);
}
/// Contract for reflected declarations
@sealed
abstract class ReflectedDeclarationContract {
/// Gets the declaration name
String get name;
/// Whether the declaration is static
bool get isStatic;
/// Gets the associated function if any
ReflectedFunctionContract? get function;
}
/// Contract for reflected classes
@sealed
abstract class ReflectedClassContract extends ReflectedTypeContract {
/// Gets the class annotations
List<ReflectedInstanceContract> get annotations;
/// Gets the class constructors
List<ReflectedFunctionContract> get constructors;
/// Gets the class declarations
List<ReflectedDeclarationContract> get declarations;
}
/// Contract for reflected instances
@sealed
abstract class ReflectedInstanceContract {
/// Gets the instance type
ReflectedTypeContract get type;
/// Gets the instance class
ReflectedClassContract get clazz;
/// Gets the actual instance being reflected
Object? get reflectee;
/// Gets a field value
ReflectedInstanceContract getField(String name);
}
/// Core reflector contract for type introspection.
///
/// This contract defines the interface for reflection capabilities,
/// allowing runtime inspection and manipulation of types, classes,
/// functions, and instances.
@sealed
abstract class ReflectorContract {
/// Gets the name from a symbol
String? getName(Symbol symbol);
/// Reflects a class type
ReflectedClassContract? reflectClass(Type clazz);
/// Reflects a function
ReflectedFunctionContract? reflectFunction(Function function);
/// Reflects a type
ReflectedTypeContract? reflectType(Type type);
/// Reflects an instance
ReflectedInstanceContract? reflectInstance(Object object);
/// Reflects the Future of a type
///
/// Throws:
/// - UnsupportedError if dart:mirrors is not available
ReflectedTypeContract reflectFutureOf(Type type);
}

View file

@ -1,2 +0,0 @@
/// Routing package contracts
export 'routing_contract.dart';

View file

@ -1,260 +0,0 @@
import 'package:meta/meta.dart';
/// Contract for router functionality.
///
/// Laravel-compatible: Core routing functionality matching Laravel's Router
/// interface, with platform-specific generic type support.
@sealed
abstract class RouterContract<T> {
/// Adds a route that responds to any HTTP method.
///
/// Laravel-compatible: Any-method route registration.
RouteContract<T> any(String path, T handler,
{Iterable<T> middleware = const []});
/// Adds a route that responds to GET requests.
///
/// Laravel-compatible: GET route registration.
RouteContract<T> get(String path, T handler,
{Iterable<T> middleware = const []});
/// Adds a route that responds to POST requests.
///
/// Laravel-compatible: POST route registration.
RouteContract<T> post(String path, T handler,
{Iterable<T> middleware = const []});
/// Adds a route that responds to PUT requests.
///
/// Laravel-compatible: PUT route registration.
RouteContract<T> put(String path, T handler,
{Iterable<T> middleware = const []});
/// Adds a route that responds to DELETE requests.
///
/// Laravel-compatible: DELETE route registration.
RouteContract<T> delete(String path, T handler,
{Iterable<T> middleware = const []});
/// Adds a route that responds to PATCH requests.
///
/// Laravel-compatible: PATCH route registration.
RouteContract<T> patch(String path, T handler,
{Iterable<T> middleware = const []});
/// Adds a route that responds to OPTIONS requests.
///
/// Laravel-compatible: OPTIONS route registration.
RouteContract<T> options(String path, T handler,
{Iterable<T> middleware = const []});
/// Creates a route group with shared attributes.
///
/// Laravel-compatible: Route grouping with platform-specific
/// callback-based configuration.
///
/// Parameters:
/// - [path]: The prefix path for the group.
/// - [callback]: Function to define routes within the group.
/// - [middleware]: Middleware to apply to all routes in the group.
void group(String path, void Function(RouterContract<T> router) callback,
{Iterable<T> middleware = const []});
/// Mounts another router at a path prefix.
///
/// Platform-specific: Provides router composition functionality.
///
/// Parameters:
/// - [path]: The path to mount at.
/// - [router]: The router to mount.
void mount(String path, RouterContract<T> router);
/// Resolves a route for a request.
///
/// Laravel-compatible: Route matching with platform-specific
/// match result contract.
///
/// Parameters:
/// - [method]: The HTTP method.
/// - [path]: The request path.
RouteMatchContract<T>? resolve(String method, String path);
}
/// Contract for route definitions.
///
/// Laravel-compatible: Route definition interface matching Laravel's Route
/// class, with platform-specific enhancements.
@sealed
abstract class RouteContract<T> {
/// Gets the route path pattern.
///
/// Laravel-compatible: Route URI pattern.
String get path;
/// Gets the HTTP method this route responds to.
///
/// Laravel-compatible: HTTP method.
String get method;
/// Gets the route handler.
///
/// Laravel-compatible: Route action with generic typing.
T get handler;
/// Gets the route middleware.
///
/// Laravel-compatible: Route middleware.
Iterable<T> get middleware;
/// Gets the route name.
///
/// Laravel-compatible: Route name accessor.
String? get name;
/// Sets the route name.
///
/// Laravel-compatible: Route name mutator.
set name(String? value);
/// Gets the route parameters.
///
/// Laravel-compatible: Route parameters.
Map<String, dynamic> get parameters;
/// Makes a URI for this route.
///
/// Laravel-compatible: URL generation.
///
/// Parameters:
/// - [params]: The parameter values to use.
String makeUri(Map<String, dynamic> params);
/// Gets the route's regular expression pattern.
///
/// Platform-specific: Direct access to route pattern.
RegExp get pattern;
/// Whether the route matches a path.
///
/// Platform-specific: Direct path matching.
bool matches(String path);
}
/// Contract for route matching results.
///
/// Platform-specific: Defines detailed match results beyond
/// Laravel's basic route matching.
@sealed
abstract class RouteMatchContract<T> {
/// Gets the matched route.
RouteContract<T> get route;
/// Gets the matched parameters.
Map<String, dynamic> get params;
/// Gets any remaining path after the match.
String get remaining;
/// Gets the full matched path.
String get matched;
}
/// Contract for route parameters.
///
/// Laravel-compatible: Parameter handling matching Laravel's
/// parameter constraints, with platform-specific validation.
@sealed
abstract class RouteParameterContract {
/// Gets the parameter name.
String get name;
/// Gets the parameter pattern.
String? get pattern;
/// Whether the parameter is optional.
bool get isOptional;
/// Gets the default value.
dynamic get defaultValue;
/// Validates a parameter value.
bool validate(String value);
}
/// Contract for route collection.
///
/// Laravel-compatible: Route collection functionality matching
/// Laravel's RouteCollection, with platform-specific enhancements.
@sealed
abstract class RouteCollectionContract<T> {
/// Gets all routes.
///
/// Laravel-compatible: Route listing.
Iterable<RouteContract<T>> get routes;
/// Gets routes by method.
///
/// Laravel-compatible: Method filtering.
Iterable<RouteContract<T>> getByMethod(String method);
/// Gets a route by name.
///
/// Laravel-compatible: Named route lookup.
RouteContract<T>? getByName(String name);
/// Adds a route to the collection.
///
/// Laravel-compatible: Route registration.
void add(RouteContract<T> route);
/// Removes a route from the collection.
///
/// Laravel-compatible: Route removal.
void remove(RouteContract<T> route);
/// Gets routes with a specific middleware.
///
/// Platform-specific: Middleware filtering.
Iterable<RouteContract<T>> getByMiddleware(T middleware);
}
/// Contract for route groups.
///
/// Laravel-compatible: Route grouping functionality matching
/// Laravel's route group features, with platform-specific additions.
@sealed
abstract class RouteGroupContract<T> {
/// Gets the group prefix.
///
/// Laravel-compatible: Group prefix.
String get prefix;
/// Gets the group middleware.
///
/// Laravel-compatible: Group middleware.
Iterable<T> get middleware;
/// Gets the group namespace.
///
/// Laravel-compatible: Group namespace.
String? get namespace;
/// Gets routes in this group.
///
/// Laravel-compatible: Group routes.
Iterable<RouteContract<T>> get routes;
/// Adds a route to the group.
///
/// Laravel-compatible: Route addition with platform-specific
/// middleware support.
RouteContract<T> addRoute(String method, String path, T handler,
{Iterable<T> middleware = const []});
/// Creates a sub-group.
///
/// Laravel-compatible: Nested grouping with platform-specific
/// namespace support.
RouteGroupContract<T> group(String prefix,
{Iterable<T> middleware = const [], String? namespace});
}

View file

@ -1,2 +0,0 @@
/// Support package contracts
export 'support_contract.dart';

View file

@ -1,263 +0,0 @@
import 'package:meta/meta.dart';
/// Contract for service providers.
///
/// Laravel-compatible: Core service provider functionality matching
/// Laravel's ServiceProvider class, adapted for Dart's type system.
@sealed
abstract class ServiceProviderContract {
/// Registers application services.
///
/// Laravel-compatible: Core registration method.
void register();
/// Bootstraps application services.
///
/// Laravel-compatible: Core bootstrap method.
void boot();
/// Gets services provided by this provider.
///
/// Laravel-compatible: Lists provided services.
List<String> provides();
/// Gets events that trigger registration.
///
/// Laravel-compatible: Lists registration triggers.
List<String> when();
/// Whether provider is deferred.
///
/// Laravel-compatible: Controls lazy loading.
bool isDeferred();
/// Gets the application instance.
///
/// Laravel-compatible: Application access.
/// Uses dynamic type for flexibility.
dynamic get app;
/// Sets the application instance.
///
/// Laravel-compatible: Application injection.
/// Uses dynamic type for flexibility.
set app(dynamic value);
/// Gets booting callbacks.
///
/// Laravel-compatible: Boot phase callbacks.
List<Function> get bootingCallbacks;
/// Gets booted callbacks.
///
/// Laravel-compatible: Post-boot callbacks.
List<Function> get bootedCallbacks;
/// Registers a booting callback.
///
/// Laravel-compatible: Boot phase hook.
void booting(Function callback);
/// Registers a booted callback.
///
/// Laravel-compatible: Post-boot hook.
void booted(Function callback);
/// Calls booting callbacks.
///
/// Laravel-compatible: Executes boot phase hooks.
void callBootingCallbacks();
/// Calls booted callbacks.
///
/// Laravel-compatible: Executes post-boot hooks.
void callBootedCallbacks();
/// Merges configuration.
///
/// Laravel-compatible: Config merging.
void mergeConfigFrom(String path, String key);
/// Replaces configuration recursively.
///
/// Laravel-compatible: Deep config replacement.
void replaceConfigRecursivelyFrom(String path, String key);
/// Loads routes from file.
///
/// Laravel-compatible: Route loading.
void loadRoutesFrom(String path);
/// Loads views from directory.
///
/// Laravel-compatible: View loading.
void loadViewsFrom(String path, String namespace);
/// Loads view components.
///
/// Laravel-compatible: Component loading.
void loadViewComponentsAs(String prefix, List<Type> components);
/// Loads translations from directory.
///
/// Laravel-compatible: Translation loading.
void loadTranslationsFrom(String path, String namespace);
/// Loads JSON translations.
///
/// Laravel-compatible: JSON translation loading.
void loadJsonTranslationsFrom(String path);
/// Loads database migrations.
///
/// Laravel-compatible: Migration loading.
void loadMigrationsFrom(dynamic paths);
/// Loads model factories.
///
/// Laravel-compatible: Factory loading.
@Deprecated('Will be removed in a future version.')
void loadFactoriesFrom(dynamic paths);
/// Sets up after resolving listener.
///
/// Laravel-compatible: Resolution hook.
void callAfterResolving(String name, Function callback);
/// Publishes migrations.
///
/// Laravel-compatible: Migration publishing.
void publishesMigrations(List<String> paths, [dynamic groups]);
/// Registers publishable paths.
///
/// Laravel-compatible: Asset publishing.
void registerPublishables(Map<String, String> paths, [dynamic groups]);
/// Legacy method for registering publishables.
///
/// Laravel-compatible: Legacy publish method.
@Deprecated('Use registerPublishables instead')
void publishes(Map<String, String> paths, [dynamic groups]);
/// Initializes publish array.
///
/// Laravel-compatible: Publish setup.
void ensurePublishArrayInitialized(String className);
/// Adds a publish group.
///
/// Laravel-compatible: Group publishing.
void addPublishGroup(String group, Map<String, String> paths);
/// Gets paths to publish.
///
/// Laravel-compatible: Publish path lookup.
Map<String, String> pathsToPublish([String? provider, String? group]);
/// Gets paths for provider or group.
///
/// Laravel-compatible: Provider/group path lookup.
Map<String, String> pathsForProviderOrGroup(String? provider, String? group);
/// Gets paths for provider and group.
///
/// Laravel-compatible: Combined path lookup.
Map<String, String> pathsForProviderAndGroup(String provider, String group);
/// Gets publishable providers.
///
/// Laravel-compatible: Provider listing.
List<String> publishableProviders();
/// Gets publishable migration paths.
///
/// Laravel-compatible: Migration path listing.
List<String> publishableMigrationPaths();
/// Gets publishable groups.
///
/// Laravel-compatible: Group listing.
List<String> publishableGroups();
/// Registers commands.
///
/// Laravel-compatible: Command registration.
void commands(List<Type> commands);
/// Gets default providers.
///
/// Laravel-compatible: Default provider listing.
List<Type> defaultProviders();
/// Adds provider to bootstrap file.
///
/// Laravel-compatible: Provider bootstrapping.
bool addProviderToBootstrapFile(String provider, [String? path]);
/// Registers a singleton.
///
/// Laravel-compatible: Singleton binding with Dart typing.
void singleton<T>(T instance);
/// Registers a factory binding.
///
/// Laravel-compatible: Factory binding with Dart typing.
void bind<T>(T Function(dynamic) factory);
/// Gets a service.
///
/// Laravel-compatible: Service resolution with Dart typing.
T make<T>([Type? type]);
/// Checks if service exists.
///
/// Laravel-compatible: Binding check with Dart typing.
bool has<T>();
/// Registers tagged bindings.
///
/// Laravel-compatible: Tag binding with Dart typing.
void tag(List<Type> abstracts, List<Type> tags);
/// Registers an event listener.
///
/// Laravel-compatible: Event listener registration.
void listen(String event, Function listener);
/// Registers middleware.
///
/// Laravel-compatible: Middleware registration.
void middleware(String name, Function handler);
}
/// Contract for deferrable providers.
///
/// Laravel-compatible: Defines providers that can be loaded
/// on demand rather than at application startup.
@sealed
abstract class DeferrableProviderContract {
/// Gets services provided by this provider.
///
/// Laravel-compatible: Lists deferred services.
List<String> provides();
}
/// Contract for provider static functionality.
///
/// Platform-specific: Provides static helper methods and properties
/// following Laravel's patterns for static configuration.
@sealed
abstract class ServiceProviderStaticContract {
/// Gets publishable migration paths.
static final List<String> publishableMigrationPaths = [];
/// Gets publishable paths.
static final Map<String, Map<String, String>> publishablePaths = {};
/// Gets publishable groups.
static final Map<String, Map<String, String>> publishableGroups = {};
/// Gets publishable provider paths.
static final Map<String, Map<String, String>> publishableProviderPaths = {};
}

View file

@ -1,2 +0,0 @@
/// Testing package contracts
export 'testing_contract.dart';

View file

@ -1,302 +0,0 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:meta/meta.dart';
/// Contract for mock HTTP requests.
///
/// This contract defines how HTTP requests should be mocked
/// for testing purposes.
@sealed
abstract class MockHttpRequestContract
implements HttpRequest, StreamSink<List<int>>, StringSink {
/// Gets the request method.
@override
String get method;
/// Gets the request URI.
@override
Uri get uri;
/// Gets request headers.
@override
HttpHeaders get headers;
/// Gets request cookies.
@override
List<Cookie> get cookies;
/// Gets connection info.
@override
HttpConnectionInfo get connectionInfo;
/// Gets request session.
@override
HttpSession get session;
/// Gets request content length.
@override
int get contentLength;
/// Gets protocol version.
@override
String get protocolVersion;
/// Gets SSL/TLS certificate.
@override
X509Certificate? get certificate;
/// Gets whether connection is persistent.
@override
bool get persistentConnection;
/// Gets requested URI.
@override
Uri get requestedUri;
/// Sets requested URI.
set requestedUri(Uri value);
/// Gets response object.
@override
HttpResponse get response;
}
/// Contract for mock HTTP responses.
///
/// This contract defines how HTTP responses should be mocked
/// for testing purposes.
@sealed
abstract class MockHttpResponseContract
implements HttpResponse, Stream<List<int>> {
/// Gets/sets status code.
@override
int get statusCode;
@override
set statusCode(int value);
/// Gets/sets reason phrase.
@override
String get reasonPhrase;
@override
set reasonPhrase(String value);
/// Gets/sets content length.
@override
int get contentLength;
@override
set contentLength(int value);
/// Gets/sets deadline.
@override
Duration? get deadline;
@override
set deadline(Duration? value);
/// Gets/sets encoding.
@override
Encoding get encoding;
@override
set encoding(Encoding value);
/// Gets/sets persistent connection flag.
@override
bool get persistentConnection;
@override
set persistentConnection(bool value);
/// Gets/sets buffer output flag.
@override
bool get bufferOutput;
@override
set bufferOutput(bool value);
/// Gets response headers.
@override
HttpHeaders get headers;
/// Gets response cookies.
@override
List<Cookie> get cookies;
/// Gets connection info.
@override
HttpConnectionInfo get connectionInfo;
/// Gets done future.
@override
Future get done;
/// Detaches socket.
@override
Future<Socket> detachSocket({bool writeHeaders = true});
/// Redirects to location.
@override
Future redirect(Uri location, {int status = HttpStatus.movedTemporarily});
}
/// Contract for mock HTTP sessions.
///
/// This contract defines how HTTP sessions should be mocked
/// for testing purposes.
@sealed
abstract class MockHttpSessionContract implements HttpSession {
/// Gets session ID.
@override
String get id;
/// Gets/sets whether session is new.
@override
bool get isNew;
@override
set isNew(bool value);
/// Gets session data.
Map<String, dynamic> get data;
/// Gets session value.
@override
dynamic operator [](Object? key);
/// Sets session value.
@override
void operator []=(dynamic key, dynamic value);
/// Removes session value.
@override
dynamic remove(Object? key);
/// Clears all session data.
@override
void clear();
/// Destroys the session.
@override
Future<void> destroy();
}
/// Contract for mock HTTP headers.
///
/// This contract defines how HTTP headers should be mocked
/// for testing purposes.
@sealed
abstract class MockHttpHeadersContract implements HttpHeaders {
/// Gets header value.
@override
String? value(String name);
/// Adds header value.
@override
void add(String name, Object value, {bool preserveHeaderCase = false});
/// Removes header.
@override
void remove(String name, Object value);
/// Removes all headers.
@override
void removeAll(String name);
/// Sets header value.
@override
void set(String name, Object value, {bool preserveHeaderCase = false});
/// Gets header values.
@override
List<String>? operator [](String name);
/// Gets all header names.
@override
List<String> get names;
/// Gets header values.
@override
Iterable<String>? getAll(String name);
/// Clears all headers.
@override
void clear();
/// Gets whether headers are mutable.
@override
bool get mutable;
/// Gets content type.
@override
ContentType? get contentType;
/// Sets content type.
@override
set contentType(ContentType? value);
/// Gets date.
@override
DateTime? get date;
/// Sets date.
@override
set date(DateTime? value);
/// Gets expires date.
@override
DateTime? get expires;
/// Sets expires date.
@override
set expires(DateTime? value);
/// Gets if-modified-since date.
@override
DateTime? get ifModifiedSince;
/// Sets if-modified-since date.
@override
set ifModifiedSince(DateTime? value);
/// Gets host.
@override
String? get host;
/// Sets host.
@override
set host(String? value);
/// Gets port.
@override
int? get port;
/// Sets port.
@override
set port(int? value);
/// Locks headers from modification.
void lock();
/// Gets whether headers are locked.
bool get locked;
}
/// Contract for mock connection info.
///
/// This contract defines how connection info should be mocked
/// for testing purposes.
@sealed
abstract class MockConnectionInfoContract implements HttpConnectionInfo {
/// Gets local address.
@override
InternetAddress get localAddress;
/// Gets local port.
@override
int get localPort;
/// Gets remote address.
@override
InternetAddress get remoteAddress;
/// Gets remote port.
@override
int get remotePort;
}

View file

@ -1,402 +0,0 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
_fe_analyzer_shared:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: "45cfa8471b89fb6643fe9bf51bd7931a76b8f5ec2d65de4fb176dba8d4f22c77"
url: "https://pub.dev"
source: hosted
version: "73.0.0"
_macros:
dependency: transitive
description: dart
source: sdk
version: "0.3.2"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: "4959fec185fe70cce007c57e9ab6983101dbe593d2bf8bbfb4453aaec0cf470a"
url: "https://pub.dev"
source: hosted
version: "6.8.0"
args:
dependency: transitive
description:
name: args
sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6
url: "https://pub.dev"
source: hosted
version: "2.6.0"
async:
dependency: transitive
description:
name: async
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
url: "https://pub.dev"
source: hosted
version: "2.12.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
collection:
dependency: transitive
description:
name: collection
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
url: "https://pub.dev"
source: hosted
version: "1.19.1"
convert:
dependency: transitive
description:
name: convert
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
url: "https://pub.dev"
source: hosted
version: "3.1.2"
coverage:
dependency: transitive
description:
name: coverage
sha256: "4b03e11f6d5b8f6e5bb5e9f7889a56fe6c5cbe942da5378ea4d4d7f73ef9dfe5"
url: "https://pub.dev"
source: hosted
version: "1.11.0"
crypto:
dependency: transitive
description:
name: crypto
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
url: "https://pub.dev"
source: hosted
version: "3.0.6"
file:
dependency: transitive
description:
name: file
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
url: "https://pub.dev"
source: hosted
version: "7.0.1"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
url: "https://pub.dev"
source: hosted
version: "4.0.0"
glob:
dependency: transitive
description:
name: glob
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
http_multi_server:
dependency: transitive
description:
name: http_multi_server
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
url: "https://pub.dev"
source: hosted
version: "3.2.1"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "76d306a1c3afb33fe82e2bbacad62a61f409b5634c915fceb0d799de1a913360"
url: "https://pub.dev"
source: hosted
version: "4.1.1"
io:
dependency: transitive
description:
name: io
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
url: "https://pub.dev"
source: hosted
version: "1.0.4"
js:
dependency: transitive
description:
name: js
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
url: "https://pub.dev"
source: hosted
version: "0.7.1"
lints:
dependency: "direct dev"
description:
name: lints
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
logging:
dependency: transitive
description:
name: logging
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
url: "https://pub.dev"
source: hosted
version: "1.3.0"
macros:
dependency: transitive
description:
name: macros
sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
url: "https://pub.dev"
source: hosted
version: "0.1.2-main.4"
matcher:
dependency: transitive
description:
name: matcher
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
url: "https://pub.dev"
source: hosted
version: "0.12.16+1"
meta:
dependency: "direct main"
description:
name: meta
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
url: "https://pub.dev"
source: hosted
version: "1.16.0"
mime:
dependency: transitive
description:
name: mime
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
node_preamble:
dependency: transitive
description:
name: node_preamble
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
package_config:
dependency: transitive
description:
name: package_config
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
path:
dependency: transitive
description:
name: path
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.dev"
source: hosted
version: "1.9.1"
pool:
dependency: transitive
description:
name: pool
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
url: "https://pub.dev"
source: hosted
version: "1.5.1"
pub_semver:
dependency: transitive
description:
name: pub_semver
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
shelf:
dependency: transitive
description:
name: shelf
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
url: "https://pub.dev"
source: hosted
version: "1.4.2"
shelf_packages_handler:
dependency: transitive
description:
name: shelf_packages_handler
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
shelf_static:
dependency: transitive
description:
name: shelf_static
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
url: "https://pub.dev"
source: hosted
version: "1.1.3"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
source_map_stack_trace:
dependency: transitive
description:
name: source_map_stack_trace
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
url: "https://pub.dev"
source: hosted
version: "2.1.2"
source_maps:
dependency: transitive
description:
name: source_maps
sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703"
url: "https://pub.dev"
source: hosted
version: "0.10.12"
source_span:
dependency: transitive
description:
name: source_span
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
url: "https://pub.dev"
source: hosted
version: "1.10.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
url: "https://pub.dev"
source: hosted
version: "1.12.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
url: "https://pub.dev"
source: hosted
version: "2.1.2"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "0bd04f5bb74fcd6ff0606a888a30e917af9bd52820b178eaa464beb11dca84b6"
url: "https://pub.dev"
source: hosted
version: "1.4.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
url: "https://pub.dev"
source: hosted
version: "1.2.1"
test:
dependency: "direct dev"
description:
name: test
sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f"
url: "https://pub.dev"
source: hosted
version: "1.25.8"
test_api:
dependency: transitive
description:
name: test_api
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
url: "https://pub.dev"
source: hosted
version: "0.7.3"
test_core:
dependency: transitive
description:
name: test_core
sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d"
url: "https://pub.dev"
source: hosted
version: "0.6.5"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
url: "https://pub.dev"
source: hosted
version: "1.4.0"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
url: "https://pub.dev"
source: hosted
version: "14.3.1"
watcher:
dependency: transitive
description:
name: watcher
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
web:
dependency: transitive
description:
name: web
sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
url: "https://pub.dev"
source: hosted
version: "1.1.0"
web_socket:
dependency: transitive
description:
name: web_socket
sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
url: "https://pub.dev"
source: hosted
version: "0.1.6"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
webkit_inspection_protocol:
dependency: transitive
description:
name: webkit_inspection_protocol
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
yaml:
dependency: transitive
description:
name: yaml
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
url: "https://pub.dev"
source: hosted
version: "3.1.2"
sdks:
dart: ">=3.5.0 <4.0.0"

View file

@ -1,13 +0,0 @@
name: platform_contracts
description: Core contracts for the Platform framework
version: 1.0.0
environment:
sdk: '>=3.0.0 <4.0.0'
dependencies:
meta: ^1.9.0
dev_dependencies:
lints: ^2.0.0
test: ^1.21.0

39
packages/cookie/README.md Normal file
View file

@ -0,0 +1,39 @@
<!--
This README describes the package. If you publish this package to pub.dev,
this README's contents appear on the landing page for your package.
For information about how to write a good package README, see the guide for
[writing package pages](https://dart.dev/guides/libraries/writing-package-pages).
For general information about developing packages, see the Dart guide for
[creating packages](https://dart.dev/guides/libraries/create-library-packages)
and the Flutter guide for
[developing packages and plugins](https://flutter.dev/developing-packages).
-->
TODO: Put a short description of the package here that helps potential users
know whether this package might be useful for them.
## Features
TODO: List what your package can do. Maybe include images, gifs, or videos.
## Getting started
TODO: List prerequisites and provide or point to information on how to
start using the package.
## Usage
TODO: Include short and useful examples for package users. Add longer examples
to `/example` folder.
```dart
const like = 'sample';
```
## Additional information
TODO: Tell users more about the package: where to find more information, how to
contribute to the package, how to file issues, what response they can expect
from the package authors, and more.

View file

View file

View file

View file

@ -1,19 +1,15 @@
name: platform_events
description: The Events Package for the Protevus Platform
name: platform_cookie
description: The Cookie Package for the Protevus Platform
version: 0.0.1
homepage: https://protevus.com
documentation: https://docs.protevus.com
repository: https://github.com/protevus/platformo
environment:
sdk: ^3.4.2
# Add regular dependencies here.
dependencies:
platform_container: ^9.0.0
angel3_mq: ^9.0.0
angel3_event_bus: ^9.0.0
platform_core: ^9.0.0
angel3_reactivex: ^0.27.5
# path: ^1.8.0
dev_dependencies:

View file

View file

@ -1,71 +0,0 @@
# See https://www.dartlang.org/tools/private-files.html
# Files and directories created by pub
.dart_tool
.packages
.pub/
build/
# If you're building an application, you may want to check-in your pubspec.lock
pubspec.lock
# Directory created by dartdoc
# If you don't generate documentation locally you can remove this line.
doc/api/
### Dart template
# See https://www.dartlang.org/tools/private-files.html
# Files and directories created by pub
# SDK 1.20 and later (no longer creates packages directories)
# Older SDK versions
# (Include if the minimum SDK version specified in pubsepc.yaml is earlier than 1.20)
.project
.buildlog
**/packages/
# Files created by dart2js
# (Most Dart developers will use pub build to compile Dart, use/modify these
# rules if you intend to use dart2js directly
# Convention is to use extension '.dart.js' for Dart compiled to Javascript to
# differentiate from explicit Javascript files)
*.dart.js
*.part.js
*.js.deps
*.js.map
*.info.json
# Directory created by dartdoc
# Don't commit pubspec lock file
# (Library packages only! Remove pattern if developing an application package)
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
## VsCode
.vscode/
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
.idea/
/out/
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

View file

@ -1,12 +0,0 @@
Primary Authors
===============
* __[Thomas Hii](dukefirehawk.apps@gmail.com)__
Thomas is the current maintainer of the code base. He has refactored and migrated the
code base to support NNBD.
* __[Tobe O](thosakwe@gmail.com)__
Tobe has written much of the original code prior to NNBD migration. He has moved on and
is no longer involved with the project.

View file

@ -1,452 +0,0 @@
# Change Log
## 8.4.0
* Require Dart >= 3.3
* Updated `lints` to 4.0.0
## 8.3.2
* Updated README
## 8.3.1
* Updated repository link
## 8.3.0
* Updated `lints` to 3.0.0
* Fixed linter warnings
## 8.2.0
* Add `addResponseHeader` to `PlatformHttp` to add headers to HTTP default response
* Add `removeResponseHeader` to `PlatformHttp` to remove headers from HTTP default response
## 8.1.1
* Updated broken image on README
## 8.1.0
* Updated `uuid` to 4.0.0
## 8.0.0
* Require Dart >= 3.0
* Updated `http` to 1.0.0
## 7.0.4
* Updated `Expose` fields to non-nullable
* Updated `Controller` to use non-nullable field
## 7.0.3
* Fixed issue #83. Allow Http request to return null headers instead of throwing an exception.
## 7.0.2
* Added performance benchmark to README
## 7.0.1
* Fixed `BytesBuilder` warnings
## 7.0.0
* Require Dart >= 2.17
## 6.0.0
* Require Dart >= 2.16
* Updated `container` to non nullable
* Updated `angel` to non nullable
* Updated `logger` to non nullable
* Refactored error handler
## 5.0.0
* Skipped release
## 4.2.4
* Fixed issue 48. Log not working in development
## 4.2.3
* Fixed `res.json()` throwing bad state exception
## 4.2.2
* Added `Date` to response header
* Updated `Server: Protevus` response header
## 4.2.1
* Updated `package:angel3_container`
## 4.2.0
* Updated to `package:belatuk_combinator`
* Updated to `package:belatuk_merge_map`
* Updated linter to `package:lints`
## 4.1.3
* Updated README
## 4.1.2
* Updated README
* Fixed NNBD issues
## 4.1.1
* Updated link to `Protevus` home page
* Fixed pedantic warnings
## 4.1.0
* Replaced `http_server` with `belatuk_http_server`
## 4.0.4
* Fixed response returning incorrect status code
## 4.0.3
* Fixed "Primitive after parsed param injection" test case
* Fixed "Cannot remove all unless explicitly set" test case
* Fixed "null" test case
## 4.0.2
* Updated README
## 4.0.1
* Updated README
## 4.0.0
* Migrated to support Dart >= 2.12 NNBD
## 3.0.0
* Migrated to work with Dart >= 2.12 Non NNBD
## 2.1.1
* `PlatformHttp.uri` now returns an empty `Uri` if the server is not listening.
## 2.1.0
* This release was originally planned to be `2.0.5`, but it adds several features, and has
therefore been bumped to `2.1.0`.
* Fix a new (did not appear before 2.6/2.7) type error causing compilation to fail.
<https://github.com/angel-dart/framework/issues/249>
## 2.0.5-beta
* Make `@Expose()` in `Controller` optional. <https://github.com/angel-dart/angel/issues/107>
* Add `allowHttp1` to `PlatformHttp2` constructors. <https://github.com/angel-dart/angel/issues/108>
* Add `deserializeBody` and `decodeBody` to `RequestContext`. <https://github.com/angel-dart/angel/issues/109>
* Add `HostnameRouter`, which allows for routing based on hostname. <https://github.com/angel-dart/angel/issues/110>
* Default to using `ThrowingReflector`, instead of `EmptyReflector`. This will give a more descriptive
error when trying to use controllers, etc. without reflection enabled.
* `mountController` returns the mounted controller.
## 2.0.4+1
* Run `Controller.configureRoutes` before mounting `@Expose` routes.
* Make `Controller.configureServer` always return a `Future`.
## 2.0.4
* Prepare for Dart SDK change to `Stream<List<int>>` that are now
`Stream<Uint8List>`.
* Accept any content type if accept header is missing. See
[this PR](https://github.com/angel-dart/framework/pull/239).
## 2.0.3
* Patch up a bug caused by an upstream change to Dart's stream semantics.
See more: <https://github.com/angel-dart/angel/issues/106#issuecomment-499564485>
## 2.0.2+1
* Fix a bug in the implementation of `Controller.applyRoutes`.
## 2.0.2
* Make `ResponseContext` *explicitly* implement `StreamConsumer` (though technically it already did???)
* Split `Controller.configureServer` to create `Controller.applyRoutes`.
## 2.0.1
* Tracked down a bug in `Driver.runPipeline` that allowed fallback
handlers to run, even after the response was closed.
* Add `RequestContext.shutdownHooks`.
* Call `RequestContext.close` in `Driver.sendResponse`.
* ProtevusConfigurer is now `FutureOr<void>`, instead of just `FutureOr`.
* Use a `Container.has<Stopwatch>` check in `Driver.sendResponse`.
* Remove unnecessary `new` and `const`.
## 2.0.0
* Protevus 2! :angel: :rocket:
## 2.0.0-rc.10
* Fix an error that prevented `PlatformHttp2.custom` from working properly.
* Add `startSharedHttp2`.
## 2.0.0-rc.9
* Fix some bugs in the `HookedService` implementation that skipped
the outputs of `before` events.
## 2.0.0-rc.8
* Fix `MapService` flaw where clients could remove all records, even if `allowRemoveAll` were `false`.
## 2.0.0-rc.7
* `AnonymousService` can override `readData`.
* `Service.map` now overrides `readData`.
* `HookedService.readData` forwards to `inner`.
## 2.0.0-rc.6
* Make `redirect` and `download` methods asynchronous.
## 2.0.0-rc.5
* Make `serializer` `FutureOr<String> Function(Object)`.
* Make `ResponseContext.serialize` return `Future<bool>`.
## 2.0.0-rc.4
* Support resolution of asynchronous injections in controllers and `ioc`.
* Inject `RequestContext` and `ResponseContext` into requests.
## 2.0.0-rc.3
* `MapService.modify` was not actually modifying items.
## 2.0.0-rc.2
* Fixes Pub analyzer lints (see `angel_route@3.0.6`)
## 2.0.0-rc.1
* Fix logic error that allowed content to be written to streaming responses after `close` was closed.
## 2.0.0-rc.0
* Log a warning when no `reflector` is provided.
* Add `ProtevusEnvironment` class.
* Add `Protevus.environment`.
* Deprecated `app.isProduction` in favor of `app.environment.isProduction`.
* Allow setting of `bodyAsObject`, `bodyAsMap`, or `bodyAsList` **exactly once**.
* Resolve named singletons in `resolveInjection`.
* Fix a bug where `Service.parseId<double>` would attempt to parse an `int`.
* Replace as Data cast in Service.dart with a method that throws a 400 on error.
## 2.0.0-alpha.24
* Add `ProtevusEnv` class to `core`.
* Deprecate `Protevus.isProduction`, in favor of `ProtevusEnv`.
## 2.0.0-alpha.23
* `ResponseContext.render` sets `charset` to `utf8` in `contentType`.
## 2.0.0-alpha.22
* Update pipeline handling mechanism, and inject a `MiddlewarePipelineIterator`.
* This allows routes to know where in the resolution process they exist, at runtime.
## 2.0.0-alpha.21
* Update for `angel_route@3.0.4` compatibility.
* Add `readAsBytes` and `readAsString` to `UploadedFile`.
* URI-decode path components in HTTP2.
## 2.0.0-alpha.20
* Inject the `MiddlewarePipeline` into requests.
## 2.0.0-alpha.19
* `parseBody` checks for null content type, and throws a `400` if none was given.
* Add `ResponseContext.contentLength`.
* Update `streamFile` to set content length, and also to work on `HEAD` requests.
## 2.0.0-alpha.18
* Upgrade `http2` dependency.
* Upgrade `uuid` dependency.
* Fixed a bug that prevented body parsing from ever completing with `http2`.
* Add `Providers.hashCode`.
## 2.0.0-alpha.17
* Revert the migration to `lumberjack` for now. In the future, when it's more
stable, there'll be a conversion, perhaps.
## 2.0.0-alpha.16
* Use `package:lumberjack` for logging.
## 2.0.0-alpha.15
* Remove dependency on `body_parser`.
* `RequestContext` now exposes a `Stream<List<int>> get body` getter.
* Calling `RequestContext.parseBody()` parses its contents.
* Added `bodyAsMap`, `bodyAsList`, `bodyAsObject`, and `uploadedFiles` to `RequestContext`.
* Removed `Protevus.keepRawRequestBuffers` and anything that had to do with buffering request bodies.
## 2.0.0-alpha.14
* Patch `HttpResponseContext._openStream` to send content-length.
## 2.0.0-alpha.13
* Fixed a logic error in `HttpResponseContext` that prevented status codes from being sent.
## 2.0.0-alpha.12
* Remove `ResponseContext.sendFile`.
* Add `Protevus.mimeTypeResolver`.
* Fix a bug where an unknown MIME type on `streamFile` would return a 500.
## 2.0.0-alpha.11
* Add `readMany` to `Service`.
* Allow `ResponseContext.redirect` to take a `Uri`.
* Add `Protevus.mountController`.
* Add `Protevus.findServiceOf`.
* Roll in HTTP/2. See `pkg:angel_framework/http2.dart`.
## 2.0.0-alpha.10
* All calls to `Service.parseId` are now affixed with the `<Id>` argument.
* Added `uri` getter to `PlatformHttp`.
* The default for `parseQuery` now wraps query parameters in `Map<String, dynamic>.from`.
This resolves a bug in `package:angel_validate`.
## 2.0.0-alpha.9
* Add `Service.map`.
## 2.0.0-alpha.8
* No longer export HTTP-specific code from `angel_framework.dart`.
An import of `import 'package:angel_framework/http.dart';` will be necessary in most cases now.
## 2.0.0-alpha.7
* Force a tigher contract on services. They now must return `Data` on all
methods except for `index`, which returns a `List<Data>`.
## 2.0.0-alpha.6
* Allow passing a custom `Container` to `handleContained` and co.
## 2.0.0-alpha.5
* `MapService` methods now explicitly return `Map<String, dynamic>`.
## 2.0.0-alpha.4
* Renamed `waterfall` to `chain`.
* Renamed `Routable.service` to `Routable.findService`.
* Also `Routable.findHookedService`.
## 2.0.0-alpha.3
* Added `<Id, Data>` type parameters to `Service`.
* `HookedService` now follows suit, and takes a third parameter, pointing to the inner service.
* `Routable.use` now uses the generic parameters added to `Service`.
* Added generic usage to `HookedServiceListener`, etc.
* All service methods take `Map<String, dynamic>` as `params` now.
## 2.0.0-alpha.2
* Added `ResponseContext.detach`.
## 2.0.0-alpha.1
* Removed `Protevus.injectEncoders`.
* Added `Providers.toJson`.
* Moved `Providers.graphql` to `Providers.graphQL`.
* `Protevus.optimizeForProduction` no longer calls `preInject`,
as it does not need to.
* Rename `ResponseContext.enableBuffer` to `ResponseContext.useBuffer`.
## 2.0.0-alpha
* Removed `random_string` dependency.
* Moved reflection to `package:angel_container`.
* Upgraded `package:file` to `5.0.0`.
* `ResponseContext.sendFile` now uses `package:file`.
* Abandon `ContentType` in favor of `MediaType`.
* Changed view engine to use `Map<String, dynamic>`.
* Remove dependency on `package:json_god` by default.
* Remove dependency on `package:dart2_constant`.
* Moved `lib/hooks.dart` into `package:angel_hooks`.
* Moved `TypedService` into `package:angel_typed_service`.
* Completely removed the `ProtevusBase` class.
* Removed all `@deprecated` symbols.
* `Service.toId` was renamed to `Service.parseId`; it also now uses its
single type argument to determine how to parse a value. \* In addition, this method was also made `static`.
* `RequestContext` and `ResponseContext` are now generic, and take a
single type argument pointing to the underlying request/response type,
respectively.
* `RequestContext.io` and `ResponseContext.io` are now permanently
gone.
* `HttpRequestContextImpl` and `HttpResponseContextImpl` were renamed to
`HttpRequestContext` and `HttpResponseContext`.
* Lazy-parsing request bodies is now the default; `Protevus.lazyParseBodies` was replaced
with `Protevus.eagerParseRequestBodies`.
* `Protevus.storeOriginalBuffer` -> `Protevus.storeRawRequestBuffers`.
* The methods `lazyBody`, `lazyFiles`, and `lazyOriginalBuffer` on `ResponseContext` were all
replaced with `parseBody`, `parseUploadedFiles`, and `parseRawRequestBuffer`, respectively.
* Removed the synchronous equivalents of the above methods (`body`, `files`, and `originalBuffer`),
as well as `query`.
* Removed `Protevus.injections` and `RequestContext.injections`.
* Removed `Protevus.inject` and `RequestContext.inject`.
* Removed a dependency on `package:pool`, which also meant removing `PlatformHttp.throttle`.
* Remove the `RequestMiddleware` typedef; from now on, one should use `ResponseContext.end`
exclusively to close responses.
* `waterfall` will now only accept `RequestHandler`.
* `Routable`, and all of its subclasses, now extend `Router<RequestHandler>`, and therefore only
take routes in the form of `FutureOr myFunc(RequestContext, ResponseContext res)`.
* `@Middleware` now takes an `Iterable` of `RequestHandler`s.
* `@Expose.path` now *must* be a `String`, not just any `Pattern`.
* `@Expose.middleware` now takes `Iterable<RequestHandler>`, instead of just `List`.
* `createDynamicHandler` was renamed to `ioc`, and is now used to run IoC-aware handlers in a
type-safe manner.
* `RequestContext.params` is now a `Map<String, dynamic>`, rather than just a `Map`.
* Removed `RequestContext.grab`.
* Removed `RequestContext.properties`.
* Removed the defunct `debug` property where it still existed.
* `Routable.use` now only accepts a `Service`.
* Removed `Protevus.createZoneForRequest`.
* Removed `Protevus.defaultZoneCreator`.
* Added all flags to the `Protevus` constructor, ex. `Protevus.eagerParseBodies`.
* Fix a bug where synchronous errors in `handleRequest` would not be caught.
* `PlatformHttp.useZone` now defaults to `false`.
* `ResponseContext` now starts in streaming mode by default; the response buffer is opt-in,
as in many cases it is unnecessary and slows down response time.
* `ResponseContext.streaming` was replaced by `ResponseContext.isBuffered`.
* Made `LockableBytesBuilder` public.
* Removed the now-obsolete `ResponseContext.willCloseItself`.
* Removed `ResponseContext.dispose`.
* Removed the now-obsolete `ResponseContext.end`.
* Removed the now-obsolete `ResponseContext.releaseCorrespondingRequest`.
* `preInject` now takes a `Reflector` as its second argument.
* `Protevus.reflector` defaults to `const EmptyReflector()`, disabling
reflection out-of-the-box.

View file

@ -1,29 +0,0 @@
BSD 3-Clause License
Copyright (c) 2021, dukefirehawk.com
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,32 +0,0 @@
# Protevus Platform Core
<p align="center"><img src="https://raw.githubusercontent.com/protevus/branding/main/protevus-logo-bg.png" alt="Protevus Logo" width="400"></p>
[![Pub Version (including pre-releases)](https://img.shields.io/pub/v/protevus_core?include_prereleases)](https://pub.dev/packages/protevus_core)
[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)
[![License](https://img.shields.io/github/license/protevus/platform)](https://github.com/protevus/platform/blob/main/packages/core/LICENSE)
Protevus Platform Core is a high-powered HTTP server framework for Dart, designed to be minimal yet extensible. It provides a robust foundation for building scalable and flexible web applications.
## Features
- Dependency injection
- Sophisticated routing
- Authentication support
- ORM integration
- GraphQL support
- Extensible plugin architecture
- HTTP/2 support
- WebSocket capabilities
- File handling and MIME type detection
- Environment configuration management
- Performance optimization with caching mechanisms
## Installation
Add `protevus_core` to your `pubspec.yaml`:
```yaml
dependencies:
protevus_core: ^latest_version
```

View file

@ -1 +0,0 @@
include: package:lints/recommended.yaml

Some files were not shown because too many files have changed in this diff Show more