refactor(zero): beginning feature branch
This commit is contained in:
parent
f2f81f11df
commit
c2a864ab38
675 changed files with 651 additions and 61127 deletions
|
@ -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';
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
// }
|
|
||||||
// }
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
// lib/src/command.dart
|
|
||||||
|
|
||||||
abstract class Command {}
|
|
||||||
|
|
||||||
abstract class ShouldQueue implements Command {}
|
|
|
@ -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];
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
import 'command.dart';
|
|
||||||
|
|
||||||
abstract class Handler {
|
|
||||||
Future<dynamic> handle(Command command);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
0
packages/config/doc/.gitkeep
Normal file
0
packages/config/doc/.gitkeep
Normal file
0
packages/config/example/.gitkeep
Normal file
0
packages/config/example/.gitkeep
Normal file
0
packages/config/lib/src/.gitkeep
Normal file
0
packages/config/lib/src/.gitkeep
Normal file
|
@ -1,18 +1,16 @@
|
||||||
name: platform_pipeline
|
name: platform_config
|
||||||
description: The Pipeline Package for the Protevus Platform
|
description: The Configuration Package for the Protevus Platform
|
||||||
version: 0.0.1
|
version: 0.0.1
|
||||||
homepage: https://protevus.com
|
homepage: https://protevus.com
|
||||||
documentation: https://docs.protevus.com
|
documentation: https://docs.protevus.com
|
||||||
repository: https://github.com/protevus/platform
|
repository: https://git.protevus.com/protevus/platform
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.4.2
|
sdk: ^3.4.2
|
||||||
|
|
||||||
# Add regular dependencies here.
|
# Add regular dependencies here.
|
||||||
dependencies:
|
dependencies:
|
||||||
platform_container: ^9.0.0
|
#protevus_runtime: ^0.0.1
|
||||||
platform_core: ^9.0.0
|
|
||||||
logging: ^1.1.0
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
lints: ^3.0.0
|
lints: ^3.0.0
|
0
packages/config/test/.gitkeep
Normal file
0
packages/config/test/.gitkeep
Normal file
71
packages/container/container/.gitignore
vendored
71
packages/container/container/.gitignore
vendored
|
@ -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
|
|
|
@ -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.
|
|
|
@ -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.
|
|
|
@ -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.
|
|
|
@ -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}");
|
|
||||||
}
|
|
||||||
```
|
|
|
@ -1 +0,0 @@
|
||||||
include: package:lints/recommended.yaml
|
|
|
@ -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.');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
import 'package:platform_container/container.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
var reflector = const ThrowingReflector();
|
|
||||||
reflector.reflectClass(StringBuffer);
|
|
||||||
}
|
|
|
@ -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';
|
|
|
@ -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';
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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._();
|
|
||||||
}
|
|
|
@ -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().');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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';
|
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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.
|
|
||||||
*/
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -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 }
|
|
|
@ -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!!!');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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});
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -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});
|
|
||||||
}
|
|
|
@ -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!!!');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -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`.
|
|
|
@ -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.
|
|
|
@ -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
|
|
|
@ -1 +0,0 @@
|
||||||
include: package:lints/recommended.yaml
|
|
|
@ -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.');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -1,2 +0,0 @@
|
||||||
/// Bus package contracts
|
|
||||||
export 'bus_contract.dart';
|
|
|
@ -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();
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
/// Container package contracts
|
|
||||||
export 'container_contract.dart';
|
|
||||||
export 'contextual_binding_contract.dart';
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
/// Events package contracts
|
|
||||||
export 'event_dispatcher_contract.dart';
|
|
|
@ -1,2 +0,0 @@
|
||||||
/// HTTP package contracts
|
|
||||||
export 'http_contract.dart';
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
/// Model package contracts
|
|
||||||
export 'model_contract.dart';
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
/// Pipeline package contracts
|
|
||||||
export 'pipeline_contract.dart';
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
/// Process package contracts
|
|
||||||
export 'process_contract.dart';
|
|
|
@ -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();
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
/// Queue package contracts
|
|
||||||
export 'queue_contract.dart';
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
/// Reflection package contracts
|
|
||||||
export 'reflector_contract.dart';
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
/// Routing package contracts
|
|
||||||
export 'routing_contract.dart';
|
|
|
@ -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});
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
/// Support package contracts
|
|
||||||
export 'support_contract.dart';
|
|
|
@ -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 = {};
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
/// Testing package contracts
|
|
||||||
export 'testing_contract.dart';
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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"
|
|
|
@ -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
39
packages/cookie/README.md
Normal 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.
|
0
packages/cookie/doc/.gitkeep
Normal file
0
packages/cookie/doc/.gitkeep
Normal file
0
packages/cookie/example/.gitkeep
Normal file
0
packages/cookie/example/.gitkeep
Normal file
0
packages/cookie/lib/src/.gitkeep
Normal file
0
packages/cookie/lib/src/.gitkeep
Normal file
|
@ -1,19 +1,15 @@
|
||||||
name: platform_events
|
name: platform_cookie
|
||||||
description: The Events Package for the Protevus Platform
|
description: The Cookie Package for the Protevus Platform
|
||||||
version: 0.0.1
|
version: 0.0.1
|
||||||
homepage: https://protevus.com
|
homepage: https://protevus.com
|
||||||
documentation: https://docs.protevus.com
|
documentation: https://docs.protevus.com
|
||||||
repository: https://github.com/protevus/platformo
|
repository: https://github.com/protevus/platformo
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.4.2
|
sdk: ^3.4.2
|
||||||
|
|
||||||
# Add regular dependencies here.
|
# Add regular dependencies here.
|
||||||
dependencies:
|
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
|
# path: ^1.8.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
0
packages/cookie/test/.gitkeep
Normal file
0
packages/cookie/test/.gitkeep
Normal file
71
packages/core/.gitignore
vendored
71
packages/core/.gitignore
vendored
|
@ -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
|
|
|
@ -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.
|
|
|
@ -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.
|
|
|
@ -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.
|
|
|
@ -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
|
|
||||||
```
|
|
|
@ -1 +0,0 @@
|
||||||
include: package:lints/recommended.yaml
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue