diff --git a/core/broadcasting/.gitignore b/core/broadcasting/.gitignore
deleted file mode 100644
index 3cceda55..00000000
--- a/core/broadcasting/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-# https://dart.dev/guides/libraries/private-files
-# Created by `dart pub`
-.dart_tool/
-
-# Avoid committing pubspec.lock for library packages; see
-# https://dart.dev/guides/libraries/private-files#pubspeclock.
-pubspec.lock
diff --git a/core/broadcasting/CHANGELOG.md b/core/broadcasting/CHANGELOG.md
deleted file mode 100644
index effe43c8..00000000
--- a/core/broadcasting/CHANGELOG.md
+++ /dev/null
@@ -1,3 +0,0 @@
-## 1.0.0
-
-- Initial version.
diff --git a/core/broadcasting/LICENSE.md b/core/broadcasting/LICENSE.md
deleted file mode 100644
index 0fd0d03b..00000000
--- a/core/broadcasting/LICENSE.md
+++ /dev/null
@@ -1,10 +0,0 @@
-The MIT License (MIT)
-
-The Laravel Framework is Copyright (c) Taylor Otwell
-The Fabric Framework is Copyright (c) Vieo, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/core/broadcasting/README.md b/core/broadcasting/README.md
deleted file mode 100644
index 757f4c9f..00000000
--- a/core/broadcasting/README.md
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/core/broadcasting/analysis_options.yaml b/core/broadcasting/analysis_options.yaml
deleted file mode 100644
index dee8927a..00000000
--- a/core/broadcasting/analysis_options.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-# This file configures the static analysis results for your project (errors,
-# warnings, and lints).
-#
-# This enables the 'recommended' set of lints from `package:lints`.
-# This set helps identify many issues that may lead to problems when running
-# or consuming Dart code, and enforces writing Dart using a single, idiomatic
-# style and format.
-#
-# If you want a smaller set of lints you can change this to specify
-# 'package:lints/core.yaml'. These are just the most critical lints
-# (the recommended set includes the core lints).
-# The core lints are also what is used by pub.dev for scoring packages.
-
-include: package:lints/recommended.yaml
-
-# Uncomment the following section to specify additional rules.
-
-# linter:
-# rules:
-# - camel_case_types
-
-# analyzer:
-# exclude:
-# - path/to/excluded/files/**
-
-# For more information about the core and recommended set of lints, see
-# https://dart.dev/go/core-lints
-
-# For additional information about configuring this file, see
-# https://dart.dev/guides/language/analysis-options
diff --git a/core/broadcasting/pubspec.yaml b/core/broadcasting/pubspec.yaml
deleted file mode 100644
index 4a763f4e..00000000
--- a/core/broadcasting/pubspec.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-name: angel3_broadcasting
-description: The Broadcasting Package for the Protevus Platform
-version: 0.0.1
-homepage: https://protevus.com
-documentation: https://docs.protevus.com
-repository: https://github.com/protevus/platformo
-
-environment:
- sdk: ^3.4.2
-
-# Add regular dependencies here.
-dependencies:
- # path: ^1.8.0
-
-dev_dependencies:
- lints: ^3.0.0
- test: ^1.24.0
diff --git a/core/broadcasting/test/.gitkeep b/core/broadcasting/test/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/core/bus/.gitignore b/core/bus/.gitignore
deleted file mode 100644
index 3cceda55..00000000
--- a/core/bus/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-# https://dart.dev/guides/libraries/private-files
-# Created by `dart pub`
-.dart_tool/
-
-# Avoid committing pubspec.lock for library packages; see
-# https://dart.dev/guides/libraries/private-files#pubspeclock.
-pubspec.lock
diff --git a/core/bus/CHANGELOG.md b/core/bus/CHANGELOG.md
deleted file mode 100644
index effe43c8..00000000
--- a/core/bus/CHANGELOG.md
+++ /dev/null
@@ -1,3 +0,0 @@
-## 1.0.0
-
-- Initial version.
diff --git a/core/bus/LICENSE.md b/core/bus/LICENSE.md
deleted file mode 100644
index 0fd0d03b..00000000
--- a/core/bus/LICENSE.md
+++ /dev/null
@@ -1,10 +0,0 @@
-The MIT License (MIT)
-
-The Laravel Framework is Copyright (c) Taylor Otwell
-The Fabric Framework is Copyright (c) Vieo, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/core/bus/README.md b/core/bus/README.md
deleted file mode 100644
index 757f4c9f..00000000
--- a/core/bus/README.md
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/core/bus/analysis_options.yaml b/core/bus/analysis_options.yaml
deleted file mode 100644
index dee8927a..00000000
--- a/core/bus/analysis_options.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-# This file configures the static analysis results for your project (errors,
-# warnings, and lints).
-#
-# This enables the 'recommended' set of lints from `package:lints`.
-# This set helps identify many issues that may lead to problems when running
-# or consuming Dart code, and enforces writing Dart using a single, idiomatic
-# style and format.
-#
-# If you want a smaller set of lints you can change this to specify
-# 'package:lints/core.yaml'. These are just the most critical lints
-# (the recommended set includes the core lints).
-# The core lints are also what is used by pub.dev for scoring packages.
-
-include: package:lints/recommended.yaml
-
-# Uncomment the following section to specify additional rules.
-
-# linter:
-# rules:
-# - camel_case_types
-
-# analyzer:
-# exclude:
-# - path/to/excluded/files/**
-
-# For more information about the core and recommended set of lints, see
-# https://dart.dev/go/core-lints
-
-# For additional information about configuring this file, see
-# https://dart.dev/guides/language/analysis-options
diff --git a/core/bus/lib/angel3_bus.dart b/core/bus/lib/angel3_bus.dart
deleted file mode 100644
index 536519b1..00000000
--- a/core/bus/lib/angel3_bus.dart
+++ /dev/null
@@ -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';
diff --git a/core/bus/lib/src/batch.dart b/core/bus/lib/src/batch.dart
deleted file mode 100644
index 5a2a24f2..00000000
--- a/core/bus/lib/src/batch.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-import 'command.dart';
-import 'dispatcher.dart';
-
-class Batch {
- // Implement Batch
-}
-
-class PendingBatch {
- final Dispatcher _dispatcher;
- final List _commands;
-
- PendingBatch(this._dispatcher, this._commands);
-
- Future dispatch() async {
- for (var command in _commands) {
- await _dispatcher.dispatch(command);
- }
- }
-}
diff --git a/core/bus/lib/src/bus_service_provider.dart b/core/bus/lib/src/bus_service_provider.dart
deleted file mode 100644
index d892653b..00000000
--- a/core/bus/lib/src/bus_service_provider.dart
+++ /dev/null
@@ -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 boot(Angel app) async {
-// // Register EventBus
-// app.container.registerSingleton(EventBus());
-
-// // Register Queue
-// app.container.registerSingleton(MemoryQueue());
-
-// // Create and register the Dispatcher
-// final dispatcher = Dispatcher(app.container);
-// app.container.registerSingleton(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 _queue = [];
-
-// @override
-// Future push(Command command) async {
-// _queue.add(command);
-// }
-
-// @override
-// Future later(Duration delay, Command command) async {
-// await Future.delayed(delay);
-// _queue.add(command);
-// }
-
-// @override
-// Future pushOn(String queue, Command command) async {
-// // For simplicity, ignoring the queue parameter in this implementation
-// _queue.add(command);
-// }
-
-// @override
-// Future laterOn(String queue, Duration delay, Command command) async {
-// // For simplicity, ignoring the queue parameter in this implementation
-// await Future.delayed(delay);
-// _queue.add(command);
-// }
-// }
diff --git a/core/bus/lib/src/chain.dart b/core/bus/lib/src/chain.dart
deleted file mode 100644
index f46dc4e9..00000000
--- a/core/bus/lib/src/chain.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-import 'command.dart';
-import 'dispatcher.dart';
-
-class PendingChain {
- final Dispatcher _dispatcher;
- final List _commands;
-
- PendingChain(this._dispatcher, this._commands);
-
- Future dispatch() async {
- for (var command in _commands) {
- await _dispatcher.dispatch(command);
- }
- }
-}
diff --git a/core/bus/lib/src/command.dart b/core/bus/lib/src/command.dart
deleted file mode 100644
index 81d5395b..00000000
--- a/core/bus/lib/src/command.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-// lib/src/command.dart
-
-abstract class Command {}
-
-abstract class ShouldQueue implements Command {}
diff --git a/core/bus/lib/src/dispatcher.dart b/core/bus/lib/src/dispatcher.dart
deleted file mode 100644
index 86c63444..00000000
--- a/core/bus/lib/src/dispatcher.dart
+++ /dev/null
@@ -1,251 +0,0 @@
-// lib/src/dispatcher.dart
-
-import 'dart:async';
-
-import 'package:angel3_container/angel3_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 _commandSubject;
- final MQClient _queue;
- final Map _handlers = {};
-
- /// Creates a new [Dispatcher] instance.
- ///
- /// [container] is used for dependency injection and to retrieve necessary services.
- Dispatcher(this.container)
- : _eventBus = container.make(),
- _commandSubject = BehaviorSubject(),
- _queue = container.make() {
- _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 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 dispatchNow(Command command, [Handler? handler]) {
- final completer = Completer();
- _commandSubject.add(command);
-
- _eventBus
- .on()
- .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 _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 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 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 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 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 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 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 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 dispatch(Command command);
- Future dispatchSync(Command command, [Handler? handler]);
- Future dispatchNow(Command command, [Handler? handler]);
- Future dispatchToQueue(Command command);
- Future findBatch(String batchId);
- PendingBatch batch(List commands);
- PendingChain chain(List commands);
- Dispatcher pipeThrough(List pipes);
- Dispatcher map(Map handlers);
- void dispatchAfterResponse(Command command);
-}
-
-typedef Pipe = Command Function(Command);
-
-class CommandCompletedEvent extends AppEvent {
- final dynamic result;
-
- CommandCompletedEvent(this.result);
-
- @override
- List get props => [result];
-}
-
-class CommandErrorEvent extends AppEvent {
- final dynamic error;
-
- CommandErrorEvent(this.error);
-
- @override
- List 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 get props => [command, result, error];
-}
diff --git a/core/bus/lib/src/handler.dart b/core/bus/lib/src/handler.dart
deleted file mode 100644
index 1c8cdfe7..00000000
--- a/core/bus/lib/src/handler.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-import 'command.dart';
-
-abstract class Handler {
- Future handle(Command command);
-}
diff --git a/core/bus/lib/src/queue.dart b/core/bus/lib/src/queue.dart
deleted file mode 100644
index 5d4b9997..00000000
--- a/core/bus/lib/src/queue.dart
+++ /dev/null
@@ -1,8 +0,0 @@
-import 'command.dart';
-
-abstract class Queue {
- Future push(Command command);
- Future later(Duration delay, Command command);
- Future pushOn(String queue, Command command);
- Future laterOn(String queue, Duration delay, Command command);
-}
diff --git a/core/bus/pubspec.yaml b/core/bus/pubspec.yaml
deleted file mode 100644
index a849fb26..00000000
--- a/core/bus/pubspec.yaml
+++ /dev/null
@@ -1,24 +0,0 @@
-name: angel3_bus
-description: The Queue Package for the Protevus Platform
-version: 0.0.1
-homepage: https://protevus.com
-documentation: https://docs.protevus.com
-repository: https://github.com/protevus/platformo
-
-environment:
- sdk: ^3.4.2
-
-# Add regular dependencies here.
-dependencies:
- angel3_container: ^9.0.0
- angel3_framework: ^9.0.0
- angel3_reactivex: ^9.0.0
- angel3_event_bus: ^9.0.0
- angel3_mq: ^9.0.0
- # path: ^1.8.0
-
-dev_dependencies:
- build_runner: ^2.1.0
- lints: ^3.0.0
- mockito: ^5.3.0
- test: ^1.24.0
diff --git a/core/bus/test/dispatcher_test.dart b/core/bus/test/dispatcher_test.dart
deleted file mode 100644
index 06e56268..00000000
--- a/core/bus/test/dispatcher_test.dart
+++ /dev/null
@@ -1,197 +0,0 @@
-import 'dart:async';
-
-import 'package:angel3_bus/angel3_bus.dart';
-import 'package:angel3_container/angel3_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 _instances = {};
-
- @override
- T make([Type? type]) {
- type ??= T;
- return _instances[type] as T;
- }
-
- void registerInstance(T instance) {
- _instances[T] = instance;
- }
-}
-
-class MockEventBus extends Mock implements EventBus {
- @override
- Stream on() {
- return super.noSuchMethod(
- Invocation.method(#on, [], {#T: T}),
- returnValue: Stream.empty(),
- ) as Stream;
- }
-}
-
-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 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);
- container.registerInstance(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(handler);
- dispatcher.map({TestCommand: TestHandler});
-
- final commandEventController = StreamController();
- when(eventBus.on())
- .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(handler);
- dispatcher.map({TestCommand: TestHandler});
-
- final commandEventController = StreamController();
- when(eventBus.on())
- .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()).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);
- });
- });
-}
diff --git a/core/console/.gitignore b/core/console/.gitignore
deleted file mode 100644
index 3cceda55..00000000
--- a/core/console/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-# https://dart.dev/guides/libraries/private-files
-# Created by `dart pub`
-.dart_tool/
-
-# Avoid committing pubspec.lock for library packages; see
-# https://dart.dev/guides/libraries/private-files#pubspeclock.
-pubspec.lock
diff --git a/core/console/CHANGELOG.md b/core/console/CHANGELOG.md
deleted file mode 100644
index effe43c8..00000000
--- a/core/console/CHANGELOG.md
+++ /dev/null
@@ -1,3 +0,0 @@
-## 1.0.0
-
-- Initial version.
diff --git a/core/console/LICENSE.md b/core/console/LICENSE.md
deleted file mode 100644
index 0fd0d03b..00000000
--- a/core/console/LICENSE.md
+++ /dev/null
@@ -1,10 +0,0 @@
-The MIT License (MIT)
-
-The Laravel Framework is Copyright (c) Taylor Otwell
-The Fabric Framework is Copyright (c) Vieo, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/core/console/README.md b/core/console/README.md
deleted file mode 100644
index 757f4c9f..00000000
--- a/core/console/README.md
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/core/console/analysis_options.yaml b/core/console/analysis_options.yaml
deleted file mode 100644
index dee8927a..00000000
--- a/core/console/analysis_options.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-# This file configures the static analysis results for your project (errors,
-# warnings, and lints).
-#
-# This enables the 'recommended' set of lints from `package:lints`.
-# This set helps identify many issues that may lead to problems when running
-# or consuming Dart code, and enforces writing Dart using a single, idiomatic
-# style and format.
-#
-# If you want a smaller set of lints you can change this to specify
-# 'package:lints/core.yaml'. These are just the most critical lints
-# (the recommended set includes the core lints).
-# The core lints are also what is used by pub.dev for scoring packages.
-
-include: package:lints/recommended.yaml
-
-# Uncomment the following section to specify additional rules.
-
-# linter:
-# rules:
-# - camel_case_types
-
-# analyzer:
-# exclude:
-# - path/to/excluded/files/**
-
-# For more information about the core and recommended set of lints, see
-# https://dart.dev/go/core-lints
-
-# For additional information about configuring this file, see
-# https://dart.dev/guides/language/analysis-options
diff --git a/core/console/lib/src/.gitkeep b/core/console/lib/src/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/core/console/pubspec.yaml b/core/console/pubspec.yaml
deleted file mode 100644
index d061c34e..00000000
--- a/core/console/pubspec.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-name: Angel3_console
-description: The Console Package for the Protevus Platform
-version: 0.0.1
-homepage: https://protevus.com
-documentation: https://docs.protevus.com
-repository: https://github.com/protevus/platformo
-
-environment:
- sdk: ^3.4.2
-
-# Add regular dependencies here.
-dependencies:
- # path: ^1.8.0
-
-dev_dependencies:
- lints: ^3.0.0
- test: ^1.24.0
diff --git a/core/console/test/.gitkeep b/core/console/test/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/core/events/.gitignore b/core/events/.gitignore
deleted file mode 100644
index 3cceda55..00000000
--- a/core/events/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-# https://dart.dev/guides/libraries/private-files
-# Created by `dart pub`
-.dart_tool/
-
-# Avoid committing pubspec.lock for library packages; see
-# https://dart.dev/guides/libraries/private-files#pubspeclock.
-pubspec.lock
diff --git a/core/events/CHANGELOG.md b/core/events/CHANGELOG.md
deleted file mode 100644
index effe43c8..00000000
--- a/core/events/CHANGELOG.md
+++ /dev/null
@@ -1,3 +0,0 @@
-## 1.0.0
-
-- Initial version.
diff --git a/core/events/LICENSE.md b/core/events/LICENSE.md
deleted file mode 100644
index 0fd0d03b..00000000
--- a/core/events/LICENSE.md
+++ /dev/null
@@ -1,10 +0,0 @@
-The MIT License (MIT)
-
-The Laravel Framework is Copyright (c) Taylor Otwell
-The Fabric Framework is Copyright (c) Vieo, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/core/events/README.md b/core/events/README.md
deleted file mode 100644
index 757f4c9f..00000000
--- a/core/events/README.md
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/core/events/analysis_options.yaml b/core/events/analysis_options.yaml
deleted file mode 100644
index dee8927a..00000000
--- a/core/events/analysis_options.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-# This file configures the static analysis results for your project (errors,
-# warnings, and lints).
-#
-# This enables the 'recommended' set of lints from `package:lints`.
-# This set helps identify many issues that may lead to problems when running
-# or consuming Dart code, and enforces writing Dart using a single, idiomatic
-# style and format.
-#
-# If you want a smaller set of lints you can change this to specify
-# 'package:lints/core.yaml'. These are just the most critical lints
-# (the recommended set includes the core lints).
-# The core lints are also what is used by pub.dev for scoring packages.
-
-include: package:lints/recommended.yaml
-
-# Uncomment the following section to specify additional rules.
-
-# linter:
-# rules:
-# - camel_case_types
-
-# analyzer:
-# exclude:
-# - path/to/excluded/files/**
-
-# For more information about the core and recommended set of lints, see
-# https://dart.dev/go/core-lints
-
-# For additional information about configuring this file, see
-# https://dart.dev/guides/language/analysis-options
diff --git a/core/events/lib/dispatcher.dart b/core/events/lib/dispatcher.dart
deleted file mode 100644
index bbc26fce..00000000
--- a/core/events/lib/dispatcher.dart
+++ /dev/null
@@ -1,3 +0,0 @@
-library;
-
-export 'src/dispatcher.dart';
diff --git a/core/events/lib/src/dispatcher.dart b/core/events/lib/src/dispatcher.dart
deleted file mode 100644
index bf2137c4..00000000
--- a/core/events/lib/src/dispatcher.dart
+++ /dev/null
@@ -1,499 +0,0 @@
-import 'dart:async';
-import 'package:angel3_container/angel3_container.dart';
-import 'package:angel3_reactivex/angel3_reactivex.dart';
-import 'package:angel3_event_bus/event_bus.dart';
-import 'package:angel3_mq/mq.dart';
-
-// Simulating some of the Laravel interfaces/classes
-abstract class ShouldBroadcast {}
-
-abstract class ShouldQueue {}
-
-abstract class ShouldBeEncrypted {}
-
-abstract class ShouldDispatchAfterCommit {}
-
-class Dispatcher implements DispatcherContract {
- // Properties as specified in YAML
- final Container container;
- final Map> _listeners = {};
- final Map> _wildcards = {};
- final Map> _wildcardsCache = {};
- late final Function _queueResolver;
- late final Function _transactionManagerResolver;
- final Map> _eventBusListeners = {};
- final Map> _untilCompleters = {};
- final Map _eventBusSubscriptions = {};
- final Set _processedMessageIds = {};
-
- // Properties for Angel3 packages
- final EventBus _eventBus;
- late final MQClient? _mqClient;
- final Map> _subjects = {};
-
- // Queue and exchange names
- static const String _eventsQueue = 'events_queue';
- static const String _delayedEventsQueue = 'delayed_events_queue';
- static const String _eventsExchange = 'events_exchange';
-
- Dispatcher(this.container) : _eventBus = EventBus();
-
- // Setter for _mqClient
- set mqClient(MQClient client) {
- _mqClient = client;
- _setupQueuesAndExchanges();
- _startProcessingQueuedEvents();
- }
-
- void _setupQueuesAndExchanges() {
- _mqClient?.declareQueue(_eventsQueue);
- _mqClient?.declareQueue(_delayedEventsQueue);
- _mqClient?.declareExchange(
- exchangeName: _eventsExchange,
- exchangeType: ExchangeType.direct,
- );
- _mqClient?.bindQueue(
- queueId: _eventsQueue,
- exchangeName: _eventsExchange,
- bindingKey: _eventsQueue,
- );
- _mqClient?.bindQueue(
- queueId: _delayedEventsQueue,
- exchangeName: _eventsExchange,
- bindingKey: _delayedEventsQueue,
- );
- }
-
- void _startProcessingQueuedEvents() {
- _mqClient?.fetchQueue(_eventsQueue).listen((Message message) async {
- if (message.payload is Map) {
- final eventData = message.payload as Map;
- if (eventData.containsKey('event') &&
- eventData.containsKey('payload')) {
- await dispatch(eventData['event'], eventData['payload']);
- } else {
- print('Invalid message format: ${message.payload}');
- }
- } else {
- print('Unexpected payload type: ${message.payload.runtimeType}');
- }
- });
- }
-
- @override
- void listen(dynamic events, dynamic listener) {
- if (events is String) {
- _addListener(events, listener);
- } else if (events is List) {
- for (var event in events) {
- _addListener(event, listener);
- }
- }
- if (events is String && events.contains('*')) {
- _setupWildcardListen(events, listener);
- }
- }
-
- void _addListener(String event, dynamic listener) {
- _listeners.putIfAbsent(event, () => []).add(listener);
-
- // Create a subject for this event if it doesn't exist
- _subjects.putIfAbsent(event, () => BehaviorSubject());
-
- // Add EventBus listener and store the subscription
- final subscription = _eventBus.on().listen((AppEvent busEvent) {
- if (busEvent is CustomAppEvent && busEvent.eventName == event) {
- listener(event, busEvent.payload);
- }
- });
- _eventBusSubscriptions[event] = subscription;
- }
-
- void _setupWildcardListen(String event, Function listener) {
- _wildcards.putIfAbsent(event, () => []).add(listener);
- _wildcardsCache.clear();
- }
-
- @override
- bool hasListeners(String eventName) {
- return _listeners.containsKey(eventName) ||
- _wildcards.containsKey(eventName) ||
- hasWildcardListeners(eventName);
- }
-
- bool hasWildcardListeners(String eventName) {
- return _wildcards.keys
- .any((pattern) => _isWildcardMatch(pattern, eventName));
- }
-
- @override
- void push(String event, [dynamic payload]) {
- final effectivePayload = payload ?? [];
- _mqClient?.sendMessage(
- exchangeName: _eventsExchange,
- routingKey: _delayedEventsQueue,
- message: Message(
- headers: {'expiration': '5000'}, // 5 seconds delay
- payload: {
- 'event': event,
- 'payload':
- effectivePayload is List ? effectivePayload : [effectivePayload],
- },
- timestamp: DateTime.now().toIso8601String(),
- id: 'msg_${DateTime.now().millisecondsSinceEpoch}', // Ensure unique ID
- ),
- );
- }
-
- @override
- Future flush(String event) async {
- final messageStream = _mqClient?.fetchQueue(_delayedEventsQueue);
- if (messageStream == null) {
- print('Warning: MQClient is not initialized');
- return;
- }
-
- final messagesToProcess = [];
-
- // Collect messages to process
- await for (final message in messageStream) {
- print('Examining message: ${message.id}');
- if (message.payload is Map &&
- !_processedMessageIds.contains(message.id)) {
- final eventData = message.payload as Map;
- if (eventData['event'] == event) {
- print('Adding message to process: ${message.id}');
- messagesToProcess.add(message);
- }
- }
- }
-
- print('Total messages to process: ${messagesToProcess.length}');
-
- // Process collected messages
- for (final message in messagesToProcess) {
- final eventData = message.payload as Map;
- print('Processing message: ${message.id}');
- await dispatch(eventData['event'], eventData['payload']);
- _mqClient?.deleteMessage(_delayedEventsQueue, message);
- _processedMessageIds.add(message.id);
- }
- }
-
- @override
- void subscribe(dynamic subscriber) {
- if (subscriber is EventBusSubscriber) {
- subscriber.subscribe(_eventBus);
- } else {
- // Handle other types of subscribers
- }
- }
-
- @override
- Future until(dynamic event, [dynamic payload]) {
- if (event is String) {
- final completer = Completer();
- _untilCompleters[event] = completer;
-
- // Set up a one-time listener for this event
- listen(event, (dynamic e, dynamic p) {
- if (!completer.isCompleted) {
- completer.complete(p);
- _untilCompleters.remove(event);
- }
- });
-
- // If payload is provided, dispatch the event immediately
- if (payload != null) {
- // Use dispatch instead of push to ensure immediate processing
- dispatch(event, payload);
- }
-
- return completer.future;
- }
- throw ArgumentError('Event must be a String');
- }
-
- @override
- Future dispatch(dynamic event, [dynamic payload, bool? halt]) async {
- final eventName = event is String ? event : event.runtimeType.toString();
- final eventPayload = payload ?? (event is AppEvent ? event : []);
-
- if (event is ShouldBroadcast ||
- (eventPayload is List &&
- eventPayload.isNotEmpty &&
- eventPayload[0] is ShouldBroadcast)) {
- await _broadcastEvent(event);
- }
-
- if (event is ShouldQueue ||
- (eventPayload is List &&
- eventPayload.isNotEmpty &&
- eventPayload[0] is ShouldQueue)) {
- return _queueEvent(eventName, eventPayload);
- }
-
- final listeners = getListeners(eventName);
- for (var listener in listeners) {
- final response =
- await Function.apply(listener, [eventName, eventPayload]);
- if (halt == true && response != null) {
- return response;
- }
- if (response == false) {
- break;
- }
- }
-
- return halt == true ? null : listeners;
- }
-
- // void _addToSubject(String eventName, dynamic payload) {
- // if (_subjects.containsKey(eventName)) {
- // _subjects[eventName]!.add(payload);
- // }
- // }
-
- @override
- List getListeners(String eventName) {
- var listeners = [
- ...(_listeners[eventName] ?? []),
- ...(_wildcardsCache[eventName] ?? _getWildcardListeners(eventName)),
- ...(_eventBusListeners[eventName] ?? []),
- ];
-
- return listeners;
- }
-
- List _getWildcardListeners(String eventName) {
- final wildcardListeners = [];
- for (var entry in _wildcards.entries) {
- if (_isWildcardMatch(entry.key, eventName)) {
- wildcardListeners.addAll(entry.value);
- }
- }
- _wildcardsCache[eventName] = wildcardListeners;
- return wildcardListeners;
- }
-
- @override
- void forget(String event) {
- // Remove from _listeners
- _listeners.remove(event);
-
- // Remove from _subjects
- if (_subjects.containsKey(event)) {
- _subjects[event]?.close();
- _subjects.remove(event);
- }
-
- // Cancel and remove EventBus subscription
- _eventBusSubscriptions[event]?.cancel();
- _eventBusSubscriptions.remove(event);
-
- // Remove from wildcards if applicable
- if (event.contains('*')) {
- _wildcards.remove(event);
- _wildcardsCache.clear();
- } else {
- // If it's not a wildcard, we need to remove it from any matching wildcard listeners
- _wildcards.forEach((pattern, listeners) {
- if (_isWildcardMatch(pattern, event)) {
- _wildcards[pattern] = listeners
- .where((listener) => listener != _listeners[event])
- .toList();
- }
- });
- _wildcardsCache.clear();
- }
-
- // Remove any 'until' completers for this event
- _untilCompleters.remove(event);
- }
-
- @override
- void forgetPushed() {
- _listeners.removeWhere((key, _) => key.endsWith('_pushed'));
- _eventBusListeners.removeWhere((key, _) => key.endsWith('_pushed'));
- // Note: We're not clearing all EventBus listeners here, as that might affect other parts of your application
- }
-
- @override
- void setQueueResolver(Function resolver) {
- _queueResolver = resolver;
- }
-
- @override
- void setTransactionManagerResolver(Function resolver) {
- _transactionManagerResolver = resolver;
- }
-
- // Add these methods for testing purposes
- void triggerQueueResolver() {
- _queueResolver();
- }
-
- void triggerTransactionManagerResolver() {
- _transactionManagerResolver();
- }
-
- @override
- Map> getRawListeners() {
- return Map.unmodifiable(_listeners);
- }
-
- bool _shouldBroadcast(List payload) {
- return payload.isNotEmpty && payload[0] is ShouldBroadcast;
- }
-
- Future _broadcastEvent(dynamic event) async {
- // Implement broadcasting logic here
- // For now, we'll just print a message
- print('Broadcasting event: ${event.runtimeType}');
- }
-
- bool _isWildcardMatch(String pattern, String eventName) {
- final regExp = RegExp('^${pattern.replaceAll('*', '.*')}\$');
- return regExp.hasMatch(eventName);
- }
-
- bool _shouldQueue(List payload) {
- return payload.isNotEmpty && payload[0] is ShouldQueue;
- }
-
- Future _queueEvent(String eventName, dynamic payload) async {
- _mqClient?.sendMessage(
- exchangeName: _eventsExchange,
- routingKey: _eventsQueue,
- message: Message(
- payload: {'event': eventName, 'payload': payload},
- timestamp: DateTime.now().toIso8601String(),
- ),
- );
- }
-
- // Updated on method
- Stream on(String event) {
- return (_subjects
- .putIfAbsent(event, () => BehaviorSubject())
- .stream as Stream)
- .where((event) => event is T)
- .cast();
- }
-
- // In your Dispatcher class
- void setMQClient(MQClient client) {
- _mqClient = client;
- }
-
- // Method to close the MQClient connection
- Future close() async {
- _mqClient?.close();
- }
-
- // Don't forget to close the subjects when they're no longer needed
- void dispose() {
- for (var subject in _subjects.values) {
- subject.close();
- }
- }
-}
-// ... rest of the code (DispatcherContract, EventBusSubscriber, etc.) remains the same
-
-abstract class DispatcherContract {
- void listen(dynamic events, dynamic listener);
- bool hasListeners(String eventName);
- void push(String event, [dynamic payload]);
- Future flush(String event);
- void subscribe(dynamic subscriber);
- Future until(dynamic event, [dynamic payload]);
- Future dispatch(dynamic event, [dynamic payload, bool halt]);
- List getListeners(String eventName);
- void forget(String event);
- void forgetPushed();
- void setQueueResolver(Function resolver);
- void setTransactionManagerResolver(Function resolver);
- Map> getRawListeners();
-}
-
-// Helper class for EventBus subscribers
-abstract class EventBusSubscriber {
- void subscribe(EventBus eventBus);
-}
-
-// Mixin to simulate Macroable trait
-mixin Macroable {
- // Implementation of Macroable functionality
-}
-
-// Mixin to simulate ReflectsClosures trait
-mixin ReflectsClosures {
- // Implementation of ReflectsClosures functionality
-}
-
-// If not already defined, you might need to create an Event class
-class Event {
- final String name;
- final dynamic data;
-
- Event(this.name, this.data);
-}
-
-// Custom AppEvent subclasses for handling different event types
-class StringBasedEvent extends AppEvent {
- final String eventName;
- final dynamic payload;
-
- StringBasedEvent(this.eventName, this.payload);
-
- @override
- List get props => [eventName, payload];
-}
-
-class CustomAppEvent extends AppEvent {
- final String eventName;
- final dynamic payload;
-
- CustomAppEvent(this.eventName, this.payload);
-
- @override
- List get props => [eventName, payload];
-}
-
-// This is a simple implementation of Reflector that does nothing
-class EmptyReflector implements Reflector {
- const EmptyReflector();
-
- @override
- ReflectedType reflectType(Type type) {
- throw UnimplementedError();
- }
-
- @override
- ReflectedInstance reflectInstance(Object object) {
- throw UnimplementedError();
- }
-
- @override
- ReflectedType reflectFutureOf(Type type) {
- throw UnimplementedError();
- }
-
- @override
- String? getName(Symbol symbol) {
- // TODO: implement getName
- throw UnimplementedError();
- }
-
- @override
- ReflectedClass? reflectClass(Type clazz) {
- // TODO: implement reflectClass
- throw UnimplementedError();
- }
-
- @override
- ReflectedFunction? reflectFunction(Function function) {
- // TODO: implement reflectFunction
- throw UnimplementedError();
- }
-}
diff --git a/core/events/pubspec.yaml b/core/events/pubspec.yaml
deleted file mode 100644
index 1e90a639..00000000
--- a/core/events/pubspec.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-name: angel3_events
-description: The Events Package for the Protevus Platform
-version: 0.0.1
-homepage: https://protevus.com
-documentation: https://docs.protevus.com
-repository: https://github.com/protevus/platformo
-environment:
- sdk: ^3.4.2
-
-# Add regular dependencies here.
-dependencies:
- angel3_container: ^9.0.0
- angel3_mq: ^9.0.0
- angel3_event_bus: ^9.0.0
- angel3_framework: ^9.0.0
- angel3_reactivex: ^0.27.5
- # path: ^1.8.0
-
-dev_dependencies:
- lints: ^3.0.0
- test: ^1.24.0
diff --git a/core/events/test/event_test.dart b/core/events/test/event_test.dart
deleted file mode 100644
index c8b6acb8..00000000
--- a/core/events/test/event_test.dart
+++ /dev/null
@@ -1,430 +0,0 @@
-import 'package:angel3_event_bus/res/app_event.dart';
-import 'package:test/test.dart';
-import 'package:angel3_container/angel3_container.dart';
-import 'package:angel3_mq/mq.dart';
-import 'package:angel3_events/dispatcher.dart'; // Replace with the actual import path
-
-void main() {
- late Dispatcher dispatcher;
- late MockMQClient mockMQClient;
-
- setUp(() {
- var container = Container(EmptyReflector());
- dispatcher = Dispatcher(container);
- mockMQClient = MockMQClient();
- dispatcher.mqClient = mockMQClient; // Use the setter
-
- // Clear the queue before each test
- mockMQClient.queuedMessages.clear();
- });
-
- group('Dispatcher', () {
- test('listen and dispatch', () async {
- var callCount = 0;
- dispatcher.listen('test_event', (dynamic event, dynamic payload) {
- expect(event, equals('test_event'));
- expect(payload, equals(['test_payload']));
- callCount++;
- });
- await dispatcher.dispatch('test_event', ['test_payload']);
- expect(callCount, equals(1));
- });
-
- test('wildcard listener', () async {
- var callCount = 0;
- dispatcher.listen('test.*', (dynamic event, dynamic payload) {
- expect(event, matches(RegExp(r'^test\.')));
- callCount++;
- });
-
- await dispatcher.dispatch('test.one', ['payload1']);
- await dispatcher.dispatch('test.two', ['payload2']);
- expect(callCount, equals(2));
- });
-
- test('hasListeners', () {
- dispatcher.listen('test_event', (dynamic event, dynamic payload) {});
- expect(dispatcher.hasListeners('test_event'), isTrue);
- expect(dispatcher.hasListeners('non_existent_event'), isFalse);
- });
-
- test('until', () async {
- // Test without pushing the event immediately
- var futureResult = dispatcher.until('test_event');
-
- // Use a small delay to ensure the until listener is set up
- await Future.delayed(Duration(milliseconds: 10));
-
- await dispatcher.dispatch('test_event', ['test_payload']);
- var result = await futureResult;
- expect(result, equals(['test_payload']));
-
- // Test with pushing the event immediately
- result =
- await dispatcher.until('another_test_event', ['another_payload']);
- expect(result, equals(['another_payload']));
- }, timeout: Timeout(Duration(seconds: 5))); // Add a reasonable timeout
-
- test('forget', () async {
- var callCount = 0;
- dispatcher.listen('test_event', (dynamic event, dynamic payload) {
- callCount++;
- });
- await dispatcher.dispatch('test_event');
- expect(callCount, equals(1));
-
- dispatcher.forget('test_event');
- await dispatcher.dispatch('test_event');
- expect(callCount, equals(1)); // Should not increase
- });
-
- test('push and flush', () async {
- print('Starting push and flush test');
-
- // Push 4 messages
- for (var i = 0; i < 4; i++) {
- dispatcher.push('delayed_event', ['delayed_payload_$i']);
- }
-
- // Verify that 4 messages were queued
- expect(mockMQClient.queuedMessages['delayed_events_queue']?.length,
- equals(4),
- reason: 'Should have queued exactly 4 messages');
-
- print(
- 'Queued messages: ${mockMQClient.queuedMessages['delayed_events_queue']?.length}');
-
- var callCount = 0;
- var processedPayloads = [];
-
- // Remove any existing listeners
- dispatcher.forget('delayed_event');
-
- dispatcher.listen('delayed_event', (dynamic event, dynamic payload) {
- print('Listener called with payload: $payload');
- expect(event, equals('delayed_event'));
- expect(payload[0], startsWith('delayed_payload_'));
- processedPayloads.add(payload[0]);
- callCount++;
- });
-
- await dispatcher.flush('delayed_event');
-
- print('After flush - Call count: $callCount');
- print('Processed payloads: $processedPayloads');
-
- expect(callCount, equals(4), reason: 'Should process exactly 4 messages');
- expect(processedPayloads.toSet().length, equals(4),
- reason: 'All payloads should be unique');
-
- // Verify that all messages were removed from the queue
- expect(mockMQClient.queuedMessages['delayed_events_queue']?.length,
- equals(0),
- reason: 'Queue should be empty after flush');
-
- // Flush again to ensure no more messages are processed
- await dispatcher.flush('delayed_event');
- expect(callCount, equals(4),
- reason: 'Should still be 4 after second flush');
- });
-
- test('shouldBroadcast', () async {
- var broadcastEvent = BroadcastTestEvent();
- var callCount = 0;
-
- dispatcher.listen('BroadcastTestEvent', (dynamic event, dynamic payload) {
- callCount++;
- });
-
- await dispatcher.dispatch(broadcastEvent);
- expect(callCount, equals(1));
- });
-
- test('shouldQueue', () async {
- var queueEvent = QueueTestEvent();
- await dispatcher.dispatch(queueEvent);
- expect(mockMQClient.queuedMessages['events_queue'], isNotEmpty);
- expect(mockMQClient.queuedMessages['events_queue']!.first.payload,
- containsPair('event', 'QueueTestEvent'));
- });
-
- test('forgetPushed removes only pushed events', () {
- dispatcher.listen('event_pushed', (_, __) {});
- dispatcher.listen('normal_event', (_, __) {});
-
- dispatcher.forgetPushed();
-
- expect(dispatcher.hasListeners('event_pushed'), isFalse);
- expect(dispatcher.hasListeners('normal_event'), isTrue);
- });
-
- test('setQueueResolver and setTransactionManagerResolver', () {
- var queueResolverCalled = false;
- var transactionManagerResolverCalled = false;
-
- dispatcher.setQueueResolver(() {
- queueResolverCalled = true;
- });
-
- dispatcher.setTransactionManagerResolver(() {
- transactionManagerResolverCalled = true;
- });
-
- // Trigger the resolvers
- dispatcher.triggerQueueResolver();
- dispatcher.triggerTransactionManagerResolver();
-
- expect(queueResolverCalled, isTrue);
- expect(transactionManagerResolverCalled, isTrue);
- });
-
- test('getRawListeners returns unmodifiable map', () {
- dispatcher.listen('test_event', (_, __) {});
- var rawListeners = dispatcher.getRawListeners();
-
- expect(rawListeners, isA>>());
- expect(() => rawListeners['new_event'] = [], throwsUnsupportedError);
- });
-
- test('multiple listeners for same event', () async {
- var callCount1 = 0;
- var callCount2 = 0;
-
- dispatcher.listen('multi_event', (_, __) => callCount1++);
- dispatcher.listen('multi_event', (_, __) => callCount2++);
-
- await dispatcher.dispatch('multi_event');
-
- expect(callCount1, equals(1));
- expect(callCount2, equals(1));
- });
- });
-}
-
-abstract class MQClientWrapper {
- Stream fetchQueue(String queueId);
- void sendMessage({
- required Message message,
- String? exchangeName,
- String? routingKey,
- });
- String declareQueue(String queueId);
- void declareExchange({
- required String exchangeName,
- required ExchangeType exchangeType,
- });
- void bindQueue({
- required String queueId,
- required String exchangeName,
- String? bindingKey,
- });
- void close();
-}
-
-class RealMQClientWrapper implements MQClientWrapper {
- final MQClient _client;
-
- RealMQClientWrapper(this._client);
-
- @override
- Stream fetchQueue(String queueId) => _client.fetchQueue(queueId);
-
- @override
- void sendMessage({
- required Message message,
- String? exchangeName,
- String? routingKey,
- }) =>
- _client.sendMessage(
- message: message,
- exchangeName: exchangeName,
- routingKey: routingKey,
- );
-
- @override
- String declareQueue(String queueId) => _client.declareQueue(queueId);
-
- @override
- void declareExchange({
- required String exchangeName,
- required ExchangeType exchangeType,
- }) =>
- _client.declareExchange(
- exchangeName: exchangeName,
- exchangeType: exchangeType,
- );
-
- @override
- void bindQueue({
- required String queueId,
- required String exchangeName,
- String? bindingKey,
- }) =>
- _client.bindQueue(
- queueId: queueId,
- exchangeName: exchangeName,
- bindingKey: bindingKey,
- );
-
- @override
- void close() => _client.close();
-}
-
-class MockMQClient implements MQClient {
- Map> queuedMessages = {};
- int _messageIdCounter = 0;
-
- void queueMessage(String queueName, Message message) {
- queuedMessages.putIfAbsent(queueName, () => []).add(message);
- print(
- 'Queued message. Queue $queueName now has ${queuedMessages[queueName]?.length} messages');
- }
-
- @override
- String declareQueue(String queueId) {
- queuedMessages[queueId] = [];
- return queueId;
- }
-
- @override
- void deleteQueue(String queueId) {
- queuedMessages.remove(queueId);
- }
-
- @override
- Stream fetchQueue(String queueId) {
- print('Fetching queue: $queueId');
- return Stream.fromIterable(queuedMessages[queueId] ?? []);
- }
-
- @override
- void sendMessage({
- required Message message,
- String? exchangeName,
- String? routingKey,
- }) {
- print('Sending message to queue: $routingKey');
- final newMessage = Message(
- payload: message.payload,
- headers: message.headers,
- timestamp: message.timestamp,
- id: 'msg_${_messageIdCounter++}',
- );
- queueMessage(routingKey ?? '', newMessage);
- }
-
- @override
- Message? getLatestMessage(String queueId) {
- final messages = queuedMessages[queueId];
- return messages?.isNotEmpty == true ? messages!.last : null;
- }
-
- @override
- void bindQueue({
- required String queueId,
- required String exchangeName,
- String? bindingKey,
- }) {
- // Implement if needed for your tests
- }
-
- @override
- void unbindQueue({
- required String queueId,
- required String exchangeName,
- String? bindingKey,
- }) {
- // Implement if needed for your tests
- }
-
- @override
- void declareExchange({
- required String exchangeName,
- required ExchangeType exchangeType,
- }) {
- // Implement if needed for your tests
- }
-
- @override
- void deleteExchange(String exchangeName) {
- // Implement if needed for your tests
- }
-
- @override
- List listQueues() {
- return queuedMessages.keys.toList();
- }
-
- @override
- void close() {
- queuedMessages.clear();
- }
-
- @override
- void deleteMessage(String queueId, Message message) {
- print('Deleting message from queue: $queueId');
- queuedMessages[queueId]?.removeWhere((m) => m.id == message.id);
- print(
- 'After deletion, queue $queueId has ${queuedMessages[queueId]?.length} messages');
- }
-}
-
-class BroadcastTestEvent implements AppEvent, ShouldBroadcast {
- @override
- List get props => [];
-
- @override
- bool? get stringify => true;
-
- @override
- DateTime get timestamp => DateTime.now();
-}
-
-class QueueTestEvent implements AppEvent, ShouldQueue {
- @override
- List get props => [];
-
- @override
- bool? get stringify => true;
-
- @override
- DateTime get timestamp => DateTime.now();
-}
-
-// This is a simple implementation of Reflector that does nothing
-class EmptyReflector implements Reflector {
- const EmptyReflector();
-
- @override
- ReflectedType reflectType(Type type) {
- throw UnimplementedError();
- }
-
- @override
- ReflectedInstance reflectInstance(Object object) {
- throw UnimplementedError();
- }
-
- @override
- ReflectedType reflectFutureOf(Type type) {
- throw UnimplementedError();
- }
-
- @override
- String? getName(Symbol symbol) {
- // TODO: implement getName
- throw UnimplementedError();
- }
-
- @override
- ReflectedClass? reflectClass(Type clazz) {
- // TODO: implement reflectClass
- throw UnimplementedError();
- }
-
- @override
- ReflectedFunction? reflectFunction(Function function) {
- // TODO: implement reflectFunction
- throw UnimplementedError();
- }
-}
diff --git a/core/pipeline/.gitignore b/core/pipeline/.gitignore
deleted file mode 100644
index 3cceda55..00000000
--- a/core/pipeline/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-# https://dart.dev/guides/libraries/private-files
-# Created by `dart pub`
-.dart_tool/
-
-# Avoid committing pubspec.lock for library packages; see
-# https://dart.dev/guides/libraries/private-files#pubspeclock.
-pubspec.lock
diff --git a/core/pipeline/CHANGELOG.md b/core/pipeline/CHANGELOG.md
deleted file mode 100644
index effe43c8..00000000
--- a/core/pipeline/CHANGELOG.md
+++ /dev/null
@@ -1,3 +0,0 @@
-## 1.0.0
-
-- Initial version.
diff --git a/core/pipeline/LICENSE.md b/core/pipeline/LICENSE.md
deleted file mode 100644
index 0fd0d03b..00000000
--- a/core/pipeline/LICENSE.md
+++ /dev/null
@@ -1,10 +0,0 @@
-The MIT License (MIT)
-
-The Laravel Framework is Copyright (c) Taylor Otwell
-The Fabric Framework is Copyright (c) Vieo, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/core/pipeline/README.md b/core/pipeline/README.md
deleted file mode 100644
index 757f4c9f..00000000
--- a/core/pipeline/README.md
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/core/pipeline/analysis_options.yaml b/core/pipeline/analysis_options.yaml
deleted file mode 100644
index dee8927a..00000000
--- a/core/pipeline/analysis_options.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-# This file configures the static analysis results for your project (errors,
-# warnings, and lints).
-#
-# This enables the 'recommended' set of lints from `package:lints`.
-# This set helps identify many issues that may lead to problems when running
-# or consuming Dart code, and enforces writing Dart using a single, idiomatic
-# style and format.
-#
-# If you want a smaller set of lints you can change this to specify
-# 'package:lints/core.yaml'. These are just the most critical lints
-# (the recommended set includes the core lints).
-# The core lints are also what is used by pub.dev for scoring packages.
-
-include: package:lints/recommended.yaml
-
-# Uncomment the following section to specify additional rules.
-
-# linter:
-# rules:
-# - camel_case_types
-
-# analyzer:
-# exclude:
-# - path/to/excluded/files/**
-
-# For more information about the core and recommended set of lints, see
-# https://dart.dev/go/core-lints
-
-# For additional information about configuring this file, see
-# https://dart.dev/guides/language/analysis-options
diff --git a/core/pipeline/examples/async_pipeline.dart b/core/pipeline/examples/async_pipeline.dart
deleted file mode 100644
index 198b2a1c..00000000
--- a/core/pipeline/examples/async_pipeline.dart
+++ /dev/null
@@ -1,38 +0,0 @@
-import 'package:angel3_framework/angel3_framework.dart';
-import 'package:angel3_framework/http.dart';
-import 'package:angel3_container/mirrors.dart';
-import 'package:angel3_pipeline/pipeline.dart';
-
-class AsyncGreetingPipe {
- Future handle(String input, Function next) async {
- await Future.delayed(Duration(seconds: 1));
- return next('Hello, $input');
- }
-}
-
-class AsyncExclamationPipe {
- Future handle(String input, Function next) async {
- await Future.delayed(Duration(seconds: 1));
- return next('$input!');
- }
-}
-
-void main() async {
- var app = Angel(reflector: MirrorsReflector());
- var http = AngelHttp(app);
-
- app.container.registerSingleton((c) => Pipeline(c));
-
- app.get('/', (req, res) async {
- var pipeline = app.container.make();
- var result = await pipeline
- .send('World')
- .through(['AsyncGreetingPipe', 'AsyncExclamationPipe']).then(
- (result) => result.toUpperCase());
-
- res.write(result); // Outputs: "HELLO, WORLD!" (after 2 seconds)
- });
-
- await http.startServer('localhost', 3000);
- print('Server started on http://localhost:3000');
-}
diff --git a/core/pipeline/examples/basic_usage.dart b/core/pipeline/examples/basic_usage.dart
deleted file mode 100644
index d8c7bdd5..00000000
--- a/core/pipeline/examples/basic_usage.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-import 'package:angel3_framework/angel3_framework.dart';
-import 'package:angel3_framework/http.dart';
-import 'package:angel3_container/mirrors.dart';
-import 'package:angel3_pipeline/pipeline.dart';
-
-class GreetingPipe {
- dynamic handle(String input, Function next) {
- return next('Hello, $input');
- }
-}
-
-class ExclamationPipe {
- dynamic handle(String input, Function next) {
- return next('$input!');
- }
-}
-
-void main() async {
- var app = Angel(reflector: MirrorsReflector());
- var http = AngelHttp(app);
-
- app.container.registerSingleton((c) => Pipeline(c));
-
- app.get('/', (req, res) async {
- var pipeline = app.container.make();
- var result = await pipeline
- .send('World')
- .through(['GreetingPipe', 'ExclamationPipe']).then(
- (result) => result.toUpperCase());
-
- res.write(result); // Outputs: "HELLO, WORLD!"
- });
-
- await http.startServer('localhost', 3000);
- print('Server started on http://localhost:3000');
-}
diff --git a/core/pipeline/examples/error_handling.dart b/core/pipeline/examples/error_handling.dart
deleted file mode 100644
index 8fb6bd7f..00000000
--- a/core/pipeline/examples/error_handling.dart
+++ /dev/null
@@ -1,34 +0,0 @@
-import 'package:angel3_framework/angel3_framework.dart';
-import 'package:angel3_framework/http.dart';
-import 'package:angel3_container/mirrors.dart';
-import 'package:angel3_pipeline/pipeline.dart';
-
-class ErrorPipe {
- dynamic handle(String input, Function next) {
- throw Exception('Simulated error');
- }
-}
-
-void main() async {
- var app = Angel(reflector: MirrorsReflector());
- var http = AngelHttp(app);
-
- app.container.registerSingleton((c) => Pipeline(c));
-
- app.get('/', (req, res) async {
- var pipeline = app.container.make();
- try {
- await pipeline
- .send('World')
- .through(['ErrorPipe']).then((result) => result.toUpperCase());
- } catch (e) {
- res.write('Error occurred: ${e.toString()}');
- return;
- }
-
- res.write('This should not be reached');
- });
-
- await http.startServer('localhost', 3000);
- print('Server started on http://localhost:3000');
-}
diff --git a/core/pipeline/examples/mixed_pipes.dart b/core/pipeline/examples/mixed_pipes.dart
deleted file mode 100644
index 18563060..00000000
--- a/core/pipeline/examples/mixed_pipes.dart
+++ /dev/null
@@ -1,35 +0,0 @@
-import 'package:angel3_framework/angel3_framework.dart';
-import 'package:angel3_framework/http.dart';
-import 'package:angel3_container/mirrors.dart';
-import 'package:angel3_pipeline/pipeline.dart';
-
-class GreetingPipe {
- dynamic handle(String input, Function next) {
- return next('Hello, $input');
- }
-}
-
-void main() async {
- var app = Angel(reflector: MirrorsReflector());
- var http = AngelHttp(app);
-
- app.container.registerSingleton((c) => Pipeline(c));
-
- app.get('/', (req, res) async {
- var pipeline = app.container.make();
- var result = await pipeline.send('World').through([
- 'GreetingPipe',
- (String input, Function next) => next('$input!'),
- (String input, Function next) async {
- await Future.delayed(Duration(seconds: 1));
- return next(input.toUpperCase());
- },
- ]).then((result) => 'Final result: $result');
-
- res.write(
- result); // Outputs: "Final result: HELLO, WORLD!" (after 1 second)
- });
-
- await http.startServer('localhost', 3000);
- print('Server started on http://localhost:3000');
-}
diff --git a/core/pipeline/lib/pipeline.dart b/core/pipeline/lib/pipeline.dart
deleted file mode 100644
index 9b73f9fb..00000000
--- a/core/pipeline/lib/pipeline.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-library;
-
-export 'src/pipeline.dart';
-export 'src/conditionable.dart';
-export 'src/pipeline_contract.dart';
diff --git a/core/pipeline/lib/src/conditionable.dart b/core/pipeline/lib/src/conditionable.dart
deleted file mode 100644
index ce796a04..00000000
--- a/core/pipeline/lib/src/conditionable.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-/// Provides conditional execution methods for the pipeline.
-mixin Conditionable {
- T when(bool Function() callback, void Function(T) callback2) {
- if (callback()) {
- callback2(this as T);
- }
- return this as T;
- }
-
- T unless(bool Function() callback, void Function(T) callback2) {
- if (!callback()) {
- callback2(this as T);
- }
- return this as T;
- }
-}
diff --git a/core/pipeline/lib/src/pipeline.dart b/core/pipeline/lib/src/pipeline.dart
deleted file mode 100644
index e5ab822c..00000000
--- a/core/pipeline/lib/src/pipeline.dart
+++ /dev/null
@@ -1,214 +0,0 @@
-import 'dart:async';
-import 'dart:mirrors';
-import 'package:angel3_container/angel3_container.dart';
-import 'package:logging/logging.dart';
-import 'pipeline_contract.dart';
-import 'conditionable.dart';
-
-/// Defines the signature for a pipe function.
-typedef PipeFunction = FutureOr Function(
- dynamic passable, FutureOr Function(dynamic) next);
-
-/// The primary class for building and executing pipelines.
-class Pipeline with Conditionable implements PipelineContract {
- /// The container implementation.
- Container? _container;
-
- final Map _typeMap = {};
-
- /// The object being passed through the pipeline.
- dynamic _passable;
-
- /// The array of class pipes.
- final List _pipes = [];
-
- /// The method to call on each pipe.
- String _method = 'handle';
-
- /// Logger for the pipeline.
- final Logger _logger = Logger('Pipeline');
-
- /// Create a new class instance.
- Pipeline(this._container);
-
- void registerPipeType(String name, Type type) {
- _typeMap[name] = type;
- }
-
- /// Set the object being sent through the pipeline.
- @override
- Pipeline send(dynamic passable) {
- _passable = passable;
- return this;
- }
-
- /// Set the array of pipes.
- @override
- Pipeline through(dynamic pipes) {
- _pipes.addAll(pipes is Iterable ? pipes.toList() : [pipes]);
- return this;
- }
-
- /// Push additional pipes onto the pipeline.
- @override
- Pipeline pipe(dynamic pipes) {
- _pipes.addAll(pipes is Iterable ? pipes.toList() : [pipes]);
- return this;
- }
-
- /// Set the method to call on the pipes.
- @override
- Pipeline via(String method) {
- _method = method;
- return this;
- }
-
- /// Run the pipeline with a final destination callback.
- @override
- Future then(FutureOr Function(dynamic) callback) async {
- PipeFunction pipeline = _pipes.fold(
- (dynamic passable, FutureOr Function(dynamic) next) async =>
- await callback(passable),
- (PipeFunction next, dynamic pipe) => (dynamic passable,
- FutureOr Function(dynamic) nextPipe) async {
- return await carry(pipe, passable,
- (dynamic result) async => await next(result, nextPipe));
- });
-
- return await pipeline(_passable, (dynamic result) async => result);
- }
-
- /// Run the pipeline and return the result.
- @override
- Future thenReturn() async {
- return then((passable) => passable);
- }
-
- /// Get the final piece of the Closure onion.
- Function prepareDestination(Function destination) {
- return (passable) async {
- try {
- var result = destination(passable);
- return result is Future ? await result : result;
- } catch (e) {
- return handleException(passable, e);
- }
- };
- }
-
- /// Get a Closure that represents a slice of the application onion.
- Future carry(dynamic pipe, dynamic passable, Function next) async {
- try {
- if (pipe is Function) {
- return await pipe(passable, next);
- }
-
- if (pipe is String) {
- if (_container == null) {
- throw Exception('Container is null, cannot resolve pipe: $pipe');
- }
-
- Type? pipeType = _typeMap[pipe];
- if (pipeType == null) {
- throw Exception('Type not registered for pipe: $pipe');
- }
-
- var instance = _container?.make(pipeType);
- if (instance == null) {
- throw Exception('Unable to resolve pipe: $pipe');
- }
-
- return await invokeMethod(instance, _method, [passable, next]);
- }
-
- throw Exception('Unsupported pipe type: ${pipe.runtimeType}');
- } catch (e) {
- return handleException(passable, e);
- }
- }
-
- /// Parse full pipe string to get name and parameters.
- List parsePipeString(String pipe) {
- var parts = pipe.split(':');
- return [parts[0], if (parts.length > 1) ...parts[1].split(',')];
- }
-
- /// Get the array of configured pipes.
- List pipes() {
- return List.unmodifiable(_pipes);
- }
-
- /// Get the container instance.
- Container getContainer() {
- if (_container == null) {
- throw Exception(
- 'A container instance has not been passed to the Pipeline.');
- }
- return _container!;
- }
-
- /// Set the container instance.
- Pipeline setContainer(Container container) {
- _container = container;
- return this;
- }
-
- /// Handle the value returned from each pipe before passing it to the next.
- dynamic handleCarry(dynamic carry) {
- if (carry is Future) {
- return carry.then((value) => value ?? _passable);
- }
- return carry ?? _passable;
- }
-
- Future invokeMethod(
- dynamic instance, String methodName, List arguments) async {
- var instanceMirror = reflect(instance);
- var methodSymbol = Symbol(methodName);
-
- if (!instanceMirror.type.declarations.containsKey(methodSymbol)) {
- throw Exception('Method $methodName not found on instance: $instance');
- }
-
- var result = instanceMirror.invoke(methodSymbol, arguments);
- return await result.reflectee;
- }
-
- /// Handle the given exception.
- dynamic handleException(dynamic passable, Object e) {
- _logger.severe('Exception occurred in pipeline', e);
- throw e;
- }
-}
-
-/// Extension methods for the Pipeline class.
-extension PipelineExtensions on Pipeline {
- /// Add a logging pipe to the pipeline.
- Pipeline addLoggingPipe() {
- return pipe((passable, next) {
- _logger.info('Pipe input: $passable');
- var result = next(passable);
- _logger.info('Pipe output: $result');
- return result;
- });
- }
-
- /// Add an asynchronous pipe to the pipeline.
- Pipeline addAsyncPipe(Future Function(dynamic) asyncOperation) {
- return pipe((passable, next) async {
- var result = await asyncOperation(passable);
- return next(result);
- });
- }
-
- /// Add a validation pipe to the pipeline.
- Pipeline addValidationPipe(bool Function(dynamic) validator,
- {String? errorMessage}) {
- return pipe((passable, next) {
- if (!validator(passable)) {
- throw Exception(errorMessage ?? 'Validation failed');
- }
- return next(passable);
- });
- }
-}
diff --git a/core/pipeline/lib/src/pipeline_contract.dart b/core/pipeline/lib/src/pipeline_contract.dart
deleted file mode 100644
index 2b45e7f8..00000000
--- a/core/pipeline/lib/src/pipeline_contract.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-/// Represents a series of "pipes" through which an object can be passed.
-abstract class PipelineContract {
- PipelineContract send(dynamic passable);
- PipelineContract through(dynamic pipes);
- PipelineContract pipe(dynamic pipes);
- PipelineContract via(String method);
- Future then(dynamic Function(dynamic) destination);
- Future thenReturn();
-}
diff --git a/core/pipeline/pubspec.yaml b/core/pipeline/pubspec.yaml
deleted file mode 100644
index 17e3e200..00000000
--- a/core/pipeline/pubspec.yaml
+++ /dev/null
@@ -1,19 +0,0 @@
-name: angel3_pipeline
-description: The Pipeline Package for the Protevus Platform
-version: 0.0.1
-homepage: https://protevus.com
-documentation: https://docs.protevus.com
-repository: https://github.com/protevus/platformo
-
-environment:
- sdk: ^3.4.2
-
-# Add regular dependencies here.
-dependencies:
- angel3_container: ^8.0.0
- angel3_framework: ^8.0.0
- logging: ^1.1.0
-
-dev_dependencies:
- lints: ^3.0.0
- test: ^1.24.0
diff --git a/core/pipeline/test/pipeline_test.dart b/core/pipeline/test/pipeline_test.dart
deleted file mode 100644
index 84a6ec9d..00000000
--- a/core/pipeline/test/pipeline_test.dart
+++ /dev/null
@@ -1,106 +0,0 @@
-import 'package:test/test.dart';
-import 'package:angel3_framework/angel3_framework.dart';
-import 'package:angel3_container/angel3_container.dart';
-import 'package:angel3_container/mirrors.dart';
-import 'package:angel3_pipeline/pipeline.dart';
-
-class AddExclamationPipe {
- Future handle(String input, Function next) async {
- return await next('$input!');
- }
-}
-
-class UppercasePipe {
- Future handle(String input, Function next) async {
- return await next(input.toUpperCase());
- }
-}
-
-void main() {
- late Angel app;
- late Container container;
- late Pipeline pipeline;
-
- setUp(() {
- app = Angel(reflector: MirrorsReflector());
- container = app.container;
- container.registerSingleton(AddExclamationPipe());
- container.registerSingleton(UppercasePipe());
- pipeline = Pipeline(container);
- pipeline.registerPipeType('AddExclamationPipe', AddExclamationPipe);
- pipeline.registerPipeType('UppercasePipe', UppercasePipe);
- });
-
- test('Pipeline should process simple string pipes', () async {
- var result = await pipeline.send('hello').through(
- ['AddExclamationPipe', 'UppercasePipe']).then((res) async => res);
- expect(result, equals('HELLO!'));
- });
-
- test('Pipeline should process function pipes', () async {
- var result = await pipeline.send('hello').through([
- (String input, Function next) async {
- var result = await next('$input, WORLD');
- return result;
- },
- (String input, Function next) async {
- var result = await next(input.toUpperCase());
- return result;
- },
- ]).then((res) async => res as String);
-
- expect(result, equals('HELLO, WORLD'));
- });
-
- test('Pipeline should handle mixed pipe types', () async {
- var result = await pipeline.send('hello').through([
- 'AddExclamationPipe',
- (String input, Function next) async {
- var result = await next(input.toUpperCase());
- return result;
- },
- ]).then((res) async => res as String);
- expect(result, equals('HELLO!'));
- });
-
- test('Pipeline should handle async pipes', () async {
- var result = await pipeline.send('hello').through([
- 'UppercasePipe',
- (String input, Function next) async {
- await Future.delayed(Duration(milliseconds: 100));
- return next('$input, WORLD');
- },
- ]).then((res) async => res as String);
- expect(result, equals('HELLO, WORLD'));
- });
-
- test('Pipeline should throw exception for unresolvable pipe', () {
- expect(
- () => pipeline
- .send('hello')
- .through(['NonExistentPipe']).then((res) => res),
- throwsA(isA()),
- );
- });
-
- test('Pipeline should allow chaining of pipes', () async {
- var result = await pipeline
- .send('hello')
- .pipe('AddExclamationPipe')
- .pipe('UppercasePipe')
- .then((res) async => res as String);
- expect(result, equals('HELLO!'));
- });
-
- test('Pipeline should respect the order of pipes', () async {
- var result1 = await pipeline
- .send('hello')
- .through(['AddExclamationPipe', 'UppercasePipe']).then((res) => res);
- var result2 = await pipeline
- .send('hello')
- .through(['UppercasePipe', 'AddExclamationPipe']).then((res) => res);
- expect(result1, equals('HELLO!'));
- expect(result2, equals('HELLO!!'));
- expect(result1, isNot(equals(result2)));
- });
-}
diff --git a/core/process/.gitignore b/core/process/.gitignore
deleted file mode 100644
index 3cceda55..00000000
--- a/core/process/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-# https://dart.dev/guides/libraries/private-files
-# Created by `dart pub`
-.dart_tool/
-
-# Avoid committing pubspec.lock for library packages; see
-# https://dart.dev/guides/libraries/private-files#pubspeclock.
-pubspec.lock
diff --git a/core/process/CHANGELOG.md b/core/process/CHANGELOG.md
deleted file mode 100644
index effe43c8..00000000
--- a/core/process/CHANGELOG.md
+++ /dev/null
@@ -1,3 +0,0 @@
-## 1.0.0
-
-- Initial version.
diff --git a/core/process/LICENSE.md b/core/process/LICENSE.md
deleted file mode 100644
index 0fd0d03b..00000000
--- a/core/process/LICENSE.md
+++ /dev/null
@@ -1,10 +0,0 @@
-The MIT License (MIT)
-
-The Laravel Framework is Copyright (c) Taylor Otwell
-The Fabric Framework is Copyright (c) Vieo, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/core/process/README.md b/core/process/README.md
deleted file mode 100644
index 757f4c9f..00000000
--- a/core/process/README.md
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/core/process/analysis_options.yaml b/core/process/analysis_options.yaml
deleted file mode 100644
index dee8927a..00000000
--- a/core/process/analysis_options.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-# This file configures the static analysis results for your project (errors,
-# warnings, and lints).
-#
-# This enables the 'recommended' set of lints from `package:lints`.
-# This set helps identify many issues that may lead to problems when running
-# or consuming Dart code, and enforces writing Dart using a single, idiomatic
-# style and format.
-#
-# If you want a smaller set of lints you can change this to specify
-# 'package:lints/core.yaml'. These are just the most critical lints
-# (the recommended set includes the core lints).
-# The core lints are also what is used by pub.dev for scoring packages.
-
-include: package:lints/recommended.yaml
-
-# Uncomment the following section to specify additional rules.
-
-# linter:
-# rules:
-# - camel_case_types
-
-# analyzer:
-# exclude:
-# - path/to/excluded/files/**
-
-# For more information about the core and recommended set of lints, see
-# https://dart.dev/go/core-lints
-
-# For additional information about configuring this file, see
-# https://dart.dev/guides/language/analysis-options
diff --git a/core/process/examples/basic_process/main.dart b/core/process/examples/basic_process/main.dart
deleted file mode 100644
index 3d425895..00000000
--- a/core/process/examples/basic_process/main.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-// examples/basic_process/main.dart
-import 'package:angel3_framework/angel3_framework.dart';
-import 'package:angel3_framework/http.dart';
-import 'package:angel3_process/angel3_process.dart';
-import 'package:logging/logging.dart';
-import 'package:angel3_container/mirrors.dart';
-
-void main() async {
- Logger.root.level = Level.ALL;
- Logger.root.onRecord.listen((record) {
- print('${record.level.name}: ${record.time}: ${record.message}');
- });
-
- // Create an Angel application with MirrorsReflector
- var app = Angel(reflector: MirrorsReflector());
- var http = AngelHttp(app);
-
- // Use dependency injection for ProcessManager
- app.container.registerSingleton(ProcessManager());
-
- app.get('/', (req, res) async {
- // Use the ioc function to get the ProcessManager instance
- var processManager = await req.container?.make();
-
- var process = await processManager?.start(
- 'example_process',
- 'echo',
- ['Hello, Angel3 Process!'],
- );
- var result = await process?.run();
- res.writeln('Process output: ${result?.output.trim()}');
- });
-
- await http.startServer('localhost', 3000);
- print('Server listening at http://localhost:3000');
-}
diff --git a/core/process/examples/process_pipeline/main.dart b/core/process/examples/process_pipeline/main.dart
deleted file mode 100644
index 29760508..00000000
--- a/core/process/examples/process_pipeline/main.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-// examples/process_pipeline/main.dart
-import 'package:angel3_framework/angel3_framework.dart';
-import 'package:angel3_framework/http.dart';
-import 'package:angel3_process/angel3_process.dart';
-import 'package:logging/logging.dart';
-import 'package:angel3_container/mirrors.dart';
-
-void main() async {
- Logger.root.level = Level.ALL;
- Logger.root.onRecord.listen((record) {
- print('${record.level.name}: ${record.time}: ${record.message}');
- });
-
- // Create an Angel application with MirrorsReflector
- var app = Angel(reflector: MirrorsReflector());
- var http = AngelHttp(app);
-
- // Register ProcessManager as a singleton in the container
- app.container.registerSingleton(ProcessManager());
-
- app.get('/', (req, res) async {
- // Use dependency injection to get the ProcessManager instance
- var processManager = await req.container?.make();
-
- var processes = [
- angel3Process('echo', ['Hello']),
- angel3Process('sed', ['s/Hello/Greetings/']),
- angel3Process('tr', ['[:lower:]', '[:upper:]']),
- ];
-
- var result = await processManager?.pipeline(processes);
- res.writeln('Pipeline output: ${result?.output.trim()}');
- });
-
- await http.startServer('localhost', 3000);
- print('Server listening at http://localhost:3000');
-}
diff --git a/core/process/examples/process_pool/main.dart b/core/process/examples/process_pool/main.dart
deleted file mode 100644
index e88f3a31..00000000
--- a/core/process/examples/process_pool/main.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-// examples/process_pool/main.dart
-import 'package:angel3_framework/angel3_framework.dart';
-import 'package:angel3_framework/http.dart';
-import 'package:angel3_process/angel3_process.dart';
-import 'package:logging/logging.dart';
-import 'package:angel3_container/mirrors.dart';
-
-void main() async {
- Logger.root.level = Level.ALL;
- Logger.root.onRecord.listen((record) {
- print('${record.level.name}: ${record.time}: ${record.message}');
- });
-
- // Create an Angel application with MirrorsReflector
- var app = Angel(reflector: MirrorsReflector());
- var http = AngelHttp(app);
-
- // Register ProcessManager as a singleton in the container
- app.container.registerSingleton(ProcessManager());
-
- app.get('/', (req, res) async {
- // Use dependency injection to get the ProcessManager instance
- var processManager = await req.container?.make();
-
- var processes =
- List.generate(5, (index) => angel3Process('echo', ['Process $index']));
- var results = await processManager?.pool(processes, concurrency: 3);
- var output = results
- ?.map((result) =>
- '${result.process.command} output: ${result.output.trim()}')
- .join('\n');
- res.write(output);
- });
-
- await http.startServer('localhost', 3000);
- print('Server listening at http://localhost:3000');
-}
diff --git a/core/process/examples/web_server_with_processes/main.dart b/core/process/examples/web_server_with_processes/main.dart
deleted file mode 100644
index 754e0284..00000000
--- a/core/process/examples/web_server_with_processes/main.dart
+++ /dev/null
@@ -1,67 +0,0 @@
-// examples/web_server_with_processes/main.dart
-import 'package:angel3_framework/angel3_framework.dart';
-import 'package:angel3_framework/http.dart';
-import 'package:angel3_process/angel3_process.dart';
-import 'package:file/local.dart';
-import 'package:logging/logging.dart';
-import 'package:angel3_mustache/angel3_mustache.dart';
-import 'package:angel3_container/mirrors.dart';
-
-void main() async {
- Logger.root.level = Level.ALL;
- Logger.root.onRecord.listen((record) {
- print('${record.level.name}: ${record.time}: ${record.message}');
- });
-
- // Create an Angel application with MirrorsReflector
- var app = Angel(reflector: MirrorsReflector());
- var http = AngelHttp(app);
-
- // Register dependencies in the container
- app.container.registerSingleton(const LocalFileSystem());
- app.container.registerSingleton(ProcessManager());
-
- // Set up the view renderer
- var fs = await app.container.make();
- var viewsDirectory = fs.directory('views');
- await app.configure(mustache(viewsDirectory));
-
- app.get('/', (req, res) async {
- await res.render('index');
- });
-
- app.post('/run-process', (req, res) async {
- var body = await req.bodyAsMap;
- var command = body['command'] as String?;
- var args = (body['args'] as String?)?.split(' ') ?? [];
-
- if (command == null || command.isEmpty) {
- throw AngelHttpException.badRequest(message: 'Command is required');
- }
-
- // Use dependency injection to get the ProcessManager instance
- var processManager = await req.container?.make();
-
- var process = await processManager?.start(
- 'user_process',
- command,
- args,
- );
- var result = await process?.run();
-
- await res.json({
- 'output': result?.output.trim(),
- 'exitCode': result?.exitCode,
- });
- });
-
- app.fallback((req, res) => throw AngelHttpException.notFound());
-
- app.errorHandler = (e, req, res) {
- res.writeln('Error: ${e.message}');
- return false;
- };
-
- await http.startServer('localhost', 3000);
- print('Server listening at http://localhost:3000');
-}
diff --git a/core/process/examples/web_server_with_processes/views/index.mustache b/core/process/examples/web_server_with_processes/views/index.mustache
deleted file mode 100644
index cb292441..00000000
--- a/core/process/examples/web_server_with_processes/views/index.mustache
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
- Angel3 Process Example
-
-
- Run a Process
-
-
-
-
-
-
diff --git a/core/process/lib/angel3_process.dart b/core/process/lib/angel3_process.dart
deleted file mode 100644
index 1965d4a2..00000000
--- a/core/process/lib/angel3_process.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-library;
-
-export 'src/process.dart';
-export 'src/process_helper.dart';
-export 'src/process_manager.dart';
-export 'src/process_pipeline.dart';
-export 'src/process_pool.dart';
diff --git a/core/process/lib/src/process.dart b/core/process/lib/src/process.dart
deleted file mode 100644
index 4049683f..00000000
--- a/core/process/lib/src/process.dart
+++ /dev/null
@@ -1,250 +0,0 @@
-import 'dart:async';
-import 'dart:io';
-import 'dart:convert';
-
-// import 'package:angel3_framework/angel3_framework.dart';
-// import 'package:angel3_mq/mq.dart';
-// import 'package:angel3_reactivex/angel3_reactivex.dart';
-// import 'package:angel3_event_bus/event_bus.dart';
-import 'package:logging/logging.dart';
-
-class Angel3Process {
- final String _command;
- final List _arguments;
- final String? _workingDirectory;
- final Map? _environment;
- final Duration? _timeout;
- final bool _tty;
- final bool _enableReadError;
- final Logger _logger;
-
- late final StreamController> _outputController;
- late final StreamController> _errorController;
- late final Completer _outputCompleter;
- late final Completer _errorCompleter;
- final Completer _errorOutputCompleter = Completer();
- bool _isOutputComplete = false;
- bool _isErrorComplete = false;
-
- Process? _process;
- DateTime? _startTime;
- DateTime? _endTime;
- bool _isDisposed = false;
-
- Angel3Process(
- this._command,
- this._arguments, {
- String? workingDirectory,
- Map? environment,
- Duration? timeout,
- bool tty = false,
- bool enableReadError = true,
- Logger? logger,
- }) : _workingDirectory = workingDirectory,
- _environment = environment,
- _timeout = timeout,
- _tty = tty,
- _enableReadError = enableReadError,
- _logger = logger ?? Logger('Angel3Process'),
- _outputController = StreamController>.broadcast(),
- _errorController = StreamController>.broadcast(),
- _outputCompleter = Completer(),
- _errorCompleter = Completer();
-
- // Add this public getter
- String get command => _command;
- int? get pid => _process?.pid;
- DateTime? get startTime => _startTime;
- DateTime? get endTime => _endTime;
-
- Stream> get output => _outputController.stream;
- Stream> get errorOutput => _errorController.stream;
-
- // Future get outputAsString => _outputCompleter.future;
- // Future get errorOutputAsString => _errorCompleter.future;
-
- Future get exitCode => _process?.exitCode ?? Future.value(-1);
- bool get isRunning => _process != null && !_process!.kill();
-
- Future start() async {
- if (_isDisposed) {
- throw StateError('This process has been disposed and cannot be reused.');
- }
- _startTime = DateTime.now();
-
- try {
- _process = await Process.start(
- _command,
- _arguments,
- workingDirectory: _workingDirectory,
- environment: _environment,
- runInShell: _tty,
- );
-
- _process!.stdout.listen(
- (data) {
- _outputController.add(data);
- },
- onDone: () {
- if (!_isOutputComplete) {
- _isOutputComplete = true;
- _outputController.close();
- }
- },
- onError: (error) {
- _logger.severe('Error in stdout stream', error);
- _outputController.addError(error);
- if (!_isOutputComplete) {
- _isOutputComplete = true;
- _outputController.close();
- }
- },
- );
-
- var errorBuffer = StringBuffer();
- _process!.stderr.listen(
- (data) {
- _errorController.add(data);
- errorBuffer.write(utf8.decode(data));
- },
- onDone: () {
- if (!_isErrorComplete) {
- _isErrorComplete = true;
- _errorController.close();
- _errorOutputCompleter.complete(errorBuffer.toString());
- }
- },
- onError: (error) {
- _logger.severe('Error in stderr stream', error);
- _errorController.addError(error);
- if (!_isErrorComplete) {
- _isErrorComplete = true;
- _errorController.close();
- _errorOutputCompleter.completeError(error);
- }
- },
- );
-
- _logger.info('Process started: $_command ${_arguments.join(' ')}');
- } catch (e) {
- _logger.severe('Failed to start process', e);
- rethrow;
- }
- return this;
- }
-
- Future run() async {
- await start();
- if (_timeout != null) {
- return await runWithTimeout(_timeout!);
- }
- final exitCode = await this.exitCode;
- final output = await outputAsString;
- final errorOutput = await _errorOutputCompleter.future;
- _endTime = DateTime.now();
- return ProcessResult(pid!, exitCode, output, errorOutput);
- }
-
- Future runWithTimeout(Duration timeout) async {
- final exitCodeFuture = this.exitCode.timeout(timeout, onTimeout: () {
- kill();
- throw TimeoutException('Process timed out', timeout);
- });
-
- try {
- final exitCode = await exitCodeFuture;
- final output = await outputAsString;
- final errorOutput = await _errorOutputCompleter.future;
- _endTime = DateTime.now();
- return ProcessResult(pid!, exitCode, output, errorOutput);
- } catch (e) {
- if (e is TimeoutException) {
- throw e;
- }
- rethrow;
- }
- }
-
- Future write(String input) async {
- if (_process != null) {
- _process!.stdin.write(input);
- await _process!.stdin.flush();
- } else {
- throw StateError('Process has not been started');
- }
- }
-
- Future writeLines(List lines) async {
- for (final line in lines) {
- await write('$line\n');
- }
- }
-
- Future kill({ProcessSignal signal = ProcessSignal.sigterm}) async {
- if (_process != null) {
- _logger.info('Killing process with signal: ${signal.name}');
- final result = _process!.kill(signal);
- if (!result) {
- _logger.warning('Failed to kill process with signal: ${signal.name}');
- }
- }
- }
-
- bool sendSignal(ProcessSignal signal) {
- return _process?.kill(signal) ?? false;
- }
-
- Future dispose() async {
- if (!_isDisposed) {
- _isDisposed = true;
- await _outputController.close();
- await _errorController.close();
- if (!_outputCompleter.isCompleted) {
- _outputCompleter.complete('');
- }
- if (!_errorCompleter.isCompleted) {
- _errorCompleter.complete('');
- }
- await kill();
- _logger.info('Process disposed: $_command ${_arguments.join(' ')}');
- }
- }
-
- Future get outputAsString async {
- var buffer = await output.transform(utf8.decoder).join();
- return buffer;
- }
-
- Future get errorOutputAsString => _errorOutputCompleter.future;
-}
-
-class ProcessResult {
- final int pid;
- final int exitCode;
- final String output;
- final String errorOutput;
-
- ProcessResult(this.pid, this.exitCode, this.output, this.errorOutput);
-
- @override
- String toString() {
- return 'ProcessResult(pid: $pid, exitCode: $exitCode, output: ${output.length} chars, errorOutput: ${errorOutput.length} chars)';
- }
-}
-
-class InvokedProcess {
- final Angel3Process process;
- final DateTime startTime;
- final DateTime endTime;
- final int exitCode;
- final String output;
- final String errorOutput;
-
- InvokedProcess(this.process, this.startTime, this.endTime, this.exitCode,
- this.output, this.errorOutput);
-
- @override
- String toString() {
- return 'InvokedProcess(command: ${process._command}, arguments: ${process._arguments}, startTime: $startTime, endTime: $endTime, exitCode: $exitCode)';
- }
-}
diff --git a/core/process/lib/src/process_helper.dart b/core/process/lib/src/process_helper.dart
deleted file mode 100644
index 5166698e..00000000
--- a/core/process/lib/src/process_helper.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-import 'process.dart';
-
-Angel3Process angel3Process(
- String command,
- List arguments, {
- String? workingDirectory,
- Map? environment,
- Duration? timeout,
- bool tty = false,
- bool enableReadError = true,
-}) {
- return Angel3Process(
- command,
- arguments,
- workingDirectory: workingDirectory,
- environment: environment,
- timeout: timeout,
- tty: tty,
- enableReadError: enableReadError,
- );
-}
diff --git a/core/process/lib/src/process_manager.dart b/core/process/lib/src/process_manager.dart
deleted file mode 100644
index f2d48b6e..00000000
--- a/core/process/lib/src/process_manager.dart
+++ /dev/null
@@ -1,148 +0,0 @@
-import 'dart:async';
-import 'dart:io';
-
-// import 'package:angel3_framework/angel3_framework.dart';
-// import 'package:angel3_mq/mq.dart';
-// import 'package:angel3_reactivex/angel3_reactivex.dart';
-import 'package:angel3_event_bus/event_bus.dart';
-import 'package:logging/logging.dart';
-
-import 'process.dart';
-import 'process_pool.dart';
-import 'process_pipeline.dart';
-
-class ProcessManager {
- final Map _processes = {};
- final EventBus _eventBus = EventBus();
- final List _subscriptions = [];
- final Logger _logger = Logger('ProcessManager');
-
- Future start(
- String id,
- String command,
- List arguments, {
- String? workingDirectory,
- Map? environment,
- Duration? timeout,
- bool tty = false,
- bool enableReadError = true,
- }) async {
- if (_processes.containsKey(id)) {
- throw Exception('Process with id $id already exists');
- }
-
- final process = Angel3Process(
- command,
- arguments,
- workingDirectory: workingDirectory,
- environment: environment,
- timeout: timeout,
- tty: tty,
- enableReadError: enableReadError,
- logger: Logger('Angel3Process:$id'),
- );
-
- try {
- await process.start();
- _processes[id] = process;
-
- _eventBus.fire(ProcessStartedEvent(id, process) as AppEvent);
-
- process.exitCode.then((exitCode) {
- _eventBus.fire(ProcessExitedEvent(id, exitCode) as AppEvent);
- _processes.remove(id);
- });
-
- _logger.info('Started process with id: $id');
- return process;
- } catch (e) {
- _logger.severe('Failed to start process with id: $id', e);
- rethrow;
- }
- }
-
- Angel3Process? get(String id) => _processes[id];
-
- Future kill(String id,
- {ProcessSignal signal = ProcessSignal.sigterm}) async {
- final process = _processes[id];
- if (process != null) {
- await process.kill(signal: signal);
- _processes.remove(id);
- _logger.info('Killed process with id: $id');
- } else {
- _logger.warning('Attempted to kill non-existent process with id: $id');
- }
- }
-
- Future killAll({ProcessSignal signal = ProcessSignal.sigterm}) async {
- _logger.info('Killing all processes');
- await Future.wait(
- _processes.values.map((process) => process.kill(signal: signal)));
- _processes.clear();
- }
-
- Stream get events => _eventBus.on();
-
- Future> pool(List processes,
- {int concurrency = 5}) async {
- _logger.info('Running process pool with concurrency: $concurrency');
- final pool = ProcessPool(concurrency: concurrency);
- return await pool.run(processes);
- }
-
- Future pipeline(List processes) async {
- _logger.info('Running process pipeline');
- final pipeline = ProcessPipeline(processes);
- return await pipeline.run();
- }
-
- void dispose() {
- _logger.info('Disposing ProcessManager');
-
- // Cancel all event subscriptions
- for (var subscription in _subscriptions) {
- subscription.cancel();
- }
- _subscriptions.clear();
-
- // Dispose all processes
- for (var process in _processes.values) {
- process.dispose();
- }
- _processes.clear();
-
- _logger.info('ProcessManager disposed');
- }
-}
-
-abstract class ProcessEvent extends AppEvent {}
-
-class ProcessStartedEvent extends ProcessEvent {
- final String id;
- final Angel3Process process;
-
- ProcessStartedEvent(this.id, this.process);
-
- @override
- String toString() =>
- 'ProcessStartedEvent(id: $id, command: ${process.command})';
-
- @override
- // TODO: implement props
- List get props => throw UnimplementedError();
-}
-
-class ProcessExitedEvent extends ProcessEvent {
- final String id;
- final int exitCode;
-
- ProcessExitedEvent(this.id, this.exitCode);
-
- @override
- String toString() => 'ProcessExitedEvent(id: $id, exitCode: $exitCode)';
-
- @override
- // TODO: implement props
- List get props => throw UnimplementedError();
-}
diff --git a/core/process/lib/src/process_pipeline.dart b/core/process/lib/src/process_pipeline.dart
deleted file mode 100644
index 449c7087..00000000
--- a/core/process/lib/src/process_pipeline.dart
+++ /dev/null
@@ -1,50 +0,0 @@
-import 'dart:async';
-import 'package:logging/logging.dart';
-import 'process.dart';
-
-class ProcessPipeline {
- final List _processes;
- final Logger _logger = Logger('ProcessPipeline');
-
- ProcessPipeline(this._processes);
-
- Future run() async {
- String input = '';
- DateTime startTime = DateTime.now();
- DateTime endTime;
- int lastExitCode = 0;
-
- _logger
- .info('Starting process pipeline with ${_processes.length} processes');
-
- for (final process in _processes) {
- _logger.info('Running process: ${process.command}');
- if (input.isNotEmpty) {
- await process.write(input);
- }
- final result = await process.run();
- input = result.output;
- lastExitCode = result.exitCode;
- _logger.info(
- 'Process completed: ${process.command} with exit code $lastExitCode');
- if (lastExitCode != 0) {
- _logger.warning(
- 'Pipeline stopped due to non-zero exit code: $lastExitCode');
- break;
- }
- }
-
- endTime = DateTime.now();
- _logger.info(
- 'Pipeline completed. Total duration: ${endTime.difference(startTime)}');
-
- return InvokedProcess(
- _processes.last,
- startTime,
- endTime,
- lastExitCode,
- input,
- '',
- );
- }
-}
diff --git a/core/process/lib/src/process_pool.dart b/core/process/lib/src/process_pool.dart
deleted file mode 100644
index 67b323ff..00000000
--- a/core/process/lib/src/process_pool.dart
+++ /dev/null
@@ -1,62 +0,0 @@
-import 'dart:async';
-import 'package:logging/logging.dart';
-import 'process.dart';
-
-class ProcessPool {
- final int concurrency;
- final List _queue = [];
- int _running = 0;
- final Logger _logger = Logger('ProcessPool');
-
- ProcessPool({this.concurrency = 5});
-
- Future> run(List processes) async {
- final results = [];
- final completer = Completer>();
-
- _logger.info('Starting process pool with ${processes.length} processes');
-
- for (final process in processes) {
- _queue.add(() async {
- try {
- final result = await _runProcess(process);
- results.add(result);
- } catch (e) {
- _logger.severe('Error running process in pool', e);
- } finally {
- _running--;
- _processQueue();
- if (_running == 0 && _queue.isEmpty) {
- completer.complete(results);
- }
- }
- });
- }
-
- _processQueue();
-
- return completer.future;
- }
-
- void _processQueue() {
- while (_running < concurrency && _queue.isNotEmpty) {
- _running++;
- _queue.removeAt(0)();
- }
- }
-
- Future _runProcess(Angel3Process process) async {
- _logger.info('Running process: ${process.command}');
- final result = await process.run();
- _logger.info(
- 'Process completed: ${process.command} with exit code ${result.exitCode}');
- return InvokedProcess(
- process,
- process.startTime!,
- process.endTime!,
- result.exitCode,
- result.output,
- result.errorOutput,
- );
- }
-}
diff --git a/core/process/lib/src/process_service_provider.dart b/core/process/lib/src/process_service_provider.dart
deleted file mode 100644
index c762c94e..00000000
--- a/core/process/lib/src/process_service_provider.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-/* import 'package:angel3_framework/angel3_framework.dart';
-import 'package:logging/logging.dart';
-import 'process_manager.dart';
-
-class ProcessServiceProvider extends Provider {
- final Logger _logger = Logger('ProcessServiceProvider');
-
- @override
- void registers() {
- container.singleton((_) => ProcessManager());
- _logger.info('Registered ProcessManager');
- }
-
- @override
- void boots(Angel app) {
- app.shutdownHooks.add((_) async {
- _logger.info('Shutting down ProcessManager');
- final processManager = app.container.make();
- await processManager.killAll();
- processManager.dispose();
- });
- _logger.info('Added ProcessManager shutdown hook');
- }
-} */
diff --git a/core/process/pubspec.yaml b/core/process/pubspec.yaml
deleted file mode 100644
index cd526f58..00000000
--- a/core/process/pubspec.yaml
+++ /dev/null
@@ -1,25 +0,0 @@
-name: angel3_process
-description: The Process Package for the Protevus Platform
-version: 0.0.1
-homepage: https://protevus.com
-documentation: https://docs.protevus.com
-repository: https://github.com/protevus/platformo
-
-environment:
- sdk: ^3.4.2
-
-# Add regular dependencies here.
-dependencies:
- angel3_container: ^8.0.0
- angel3_framework: ^8.0.0
- angel3_mq: ^8.0.0
- angel3_mustache: ^8.0.0
- angel3_event_bus: ^8.0.0
- angel3_reactivex: ^8.0.0
- file: ^7.0.0
- logging: ^1.1.0
- path: ^1.8.0
-
-dev_dependencies:
- lints: ^3.0.0
- test: ^1.24.0
diff --git a/core/process/test/process_test.dart b/core/process/test/process_test.dart
deleted file mode 100644
index f737d084..00000000
--- a/core/process/test/process_test.dart
+++ /dev/null
@@ -1,80 +0,0 @@
-import 'dart:async';
-import 'dart:convert';
-import 'dart:io';
-import 'package:angel3_process/angel3_process.dart';
-import 'package:test/test.dart';
-
-void main() {
- late Angel3Process process;
-
- setUp(() {
- process = Angel3Process('echo', ['Hello, World!']);
- });
-
- tearDown(() async {
- await process.dispose();
- });
-
- test('Angel3Process initialization', () {
- expect(process.command, equals('echo'));
- expect(process.startTime, isNull);
- expect(process.endTime, isNull);
- });
-
- test('Start and run a simple process', () async {
- var result = await process.run();
- expect(process.startTime, isNotNull);
- expect(result.exitCode, equals(0));
- expect(result.output.trim(), equals('Hello, World!'));
- expect(process.endTime, isNotNull);
- });
-
- test('Stream output', () async {
- await process.start();
- var outputStream = process.output.transform(utf8.decoder);
- var streamOutput = await outputStream.join();
- await process.exitCode; // Wait for the process to complete
- expect(streamOutput.trim(), equals('Hello, World!'));
- });
-
- test('Error output for non-existent command', () {
- var errorProcess = Angel3Process('non_existent_command', []);
- expect(errorProcess.start(), throwsA(isA()));
- });
-
- test('Process with error output', () async {
- Angel3Process errorProcess;
- if (Platform.isWindows) {
- errorProcess = Angel3Process('cmd', ['/c', 'dir', '/invalid_argument']);
- } else {
- errorProcess = Angel3Process('ls', ['/non_existent_directory']);
- }
-
- print('Starting error process...');
- var result = await errorProcess.run();
- print('Error process completed.');
- print('Exit code: ${result.exitCode}');
- print('Standard output: "${result.output}"');
- print('Error output: "${result.errorOutput}"');
-
- expect(result.exitCode, isNot(0), reason: 'Expected non-zero exit code');
- expect(result.errorOutput.trim(), isNotEmpty,
- reason: 'Expected non-empty error output');
-
- await errorProcess.dispose();
- });
-
- test('Kill running process', () async {
- var longRunningProcess = Angel3Process('sleep', ['5']);
- await longRunningProcess.start();
- await longRunningProcess.kill();
- var exitCode = await longRunningProcess.exitCode;
- expect(exitCode, isNot(0));
- });
-
- test('Process timeout', () async {
- var timeoutProcess =
- Angel3Process('sleep', ['10'], timeout: Duration(seconds: 1));
- expect(() => timeoutProcess.run(), throwsA(isA()));
- }, timeout: Timeout(Duration(seconds: 5)));
-}
diff --git a/core/process/test/process_test_extended.dart b/core/process/test/process_test_extended.dart
deleted file mode 100644
index ba18bd42..00000000
--- a/core/process/test/process_test_extended.dart
+++ /dev/null
@@ -1,102 +0,0 @@
-import 'dart:async';
-import 'dart:io' show Directory, Platform, ProcessSignal;
-import 'package:angel3_process/angel3_process.dart';
-import 'package:test/test.dart';
-import 'package:path/path.dart' as path;
-
-void main() {
- late Angel3Process process;
-
- setUp(() {
- process = Angel3Process('echo', ['Hello, World!']);
- });
-
- tearDown(() async {
- await process.dispose();
- });
-
- // ... (existing tests remain the same)
-
- test('Process with custom environment variables', () async {
- var command = Platform.isWindows ? 'cmd' : 'sh';
- var args = Platform.isWindows
- ? ['/c', 'echo %TEST_VAR%']
- : ['-c', r'echo $TEST_VAR']; // Use a raw string for Unix-like systems
-
- var envProcess =
- Angel3Process(command, args, environment: {'TEST_VAR': 'custom_value'});
-
- var result = await envProcess.run();
- expect(result.output.trim(), equals('custom_value'));
- });
-
- test('Process with custom working directory', () async {
- var tempDir = Directory.systemTemp.createTempSync();
- try {
- var workingDirProcess = Angel3Process(Platform.isWindows ? 'cmd' : 'pwd',
- Platform.isWindows ? ['/c', 'cd'] : [],
- workingDirectory: tempDir.path);
- var result = await workingDirProcess.run();
- expect(path.equals(result.output.trim(), tempDir.path), isTrue);
- } finally {
- tempDir.deleteSync();
- }
- });
-
- test('Process with input', () async {
- var catProcess = Angel3Process('cat', []);
- await catProcess.start();
- catProcess.write('Hello, stdin!');
- await catProcess.kill(); // End the process
- var output = await catProcess.outputAsString;
- expect(output.trim(), equals('Hello, stdin!'));
- });
-
- test('Longer-running process', () async {
- var sleepProcess = Angel3Process(Platform.isWindows ? 'timeout' : 'sleep',
- Platform.isWindows ? ['/t', '2'] : ['2']);
- var startTime = DateTime.now();
- await sleepProcess.run();
- var endTime = DateTime.now();
- expect(endTime.difference(startTime).inSeconds, greaterThanOrEqualTo(2));
- });
-
- test('Multiple concurrent processes', () async {
- var processes =
- List.generate(5, (_) => Angel3Process('echo', ['concurrent']));
- var results = await Future.wait(processes.map((p) => p.run()));
- for (var result in results) {
- expect(result.output.trim(), equals('concurrent'));
- }
- });
-
- test('Process signaling', () async {
- if (!Platform.isWindows) {
- // SIGSTOP/SIGCONT are not available on Windows
- var longProcess = Angel3Process('sleep', ['10']);
- await longProcess.start();
- await longProcess.sendSignal(ProcessSignal.sigstop);
- // Process should be stopped, so it shouldn't complete immediately
- expect(longProcess.exitCode, doesNotComplete);
- await longProcess.sendSignal(ProcessSignal.sigcont);
- await longProcess.kill();
- expect(await longProcess.exitCode, isNot(0));
- }
- });
-
- test('Edge case: empty command', () {
- expect(() => Angel3Process('', []), throwsA(isA()));
- });
-
- test('Edge case: empty arguments list', () {
- // This should not throw an error
- expect(() => Angel3Process('echo', []), returnsNormally);
- });
-
- test('Edge case: invalid argument type', () {
- // This should throw a compile-time error, but we can't test for that directly
- // Instead, we can test for runtime type checking if implemented
- expect(() => Angel3Process('echo', [1, 2, 3] as dynamic),
- throwsA(isA()));
- });
-}
diff --git a/core/queue/.gitignore b/core/queue/.gitignore
deleted file mode 100644
index 0b4272db..00000000
--- a/core/queue/.gitignore
+++ /dev/null
@@ -1,10 +0,0 @@
-# https://dart.dev/guides/libraries/private-files
-# Created by `dart pub`
-.dart_tool/
-
-# Avoid committing pubspec.lock for library packages; see
-# https://dart.dev/guides/libraries/private-files#pubspeclock.
-pubspec.lock
-
-*.mocks.dart
-*.reflectable.dart
diff --git a/core/queue/CHANGELOG.md b/core/queue/CHANGELOG.md
deleted file mode 100644
index effe43c8..00000000
--- a/core/queue/CHANGELOG.md
+++ /dev/null
@@ -1,3 +0,0 @@
-## 1.0.0
-
-- Initial version.
diff --git a/core/queue/LICENSE.md b/core/queue/LICENSE.md
deleted file mode 100644
index 0fd0d03b..00000000
--- a/core/queue/LICENSE.md
+++ /dev/null
@@ -1,10 +0,0 @@
-The MIT License (MIT)
-
-The Laravel Framework is Copyright (c) Taylor Otwell
-The Fabric Framework is Copyright (c) Vieo, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/core/queue/README.md b/core/queue/README.md
deleted file mode 100644
index 757f4c9f..00000000
--- a/core/queue/README.md
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/core/queue/analysis_options.yaml b/core/queue/analysis_options.yaml
deleted file mode 100644
index dee8927a..00000000
--- a/core/queue/analysis_options.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-# This file configures the static analysis results for your project (errors,
-# warnings, and lints).
-#
-# This enables the 'recommended' set of lints from `package:lints`.
-# This set helps identify many issues that may lead to problems when running
-# or consuming Dart code, and enforces writing Dart using a single, idiomatic
-# style and format.
-#
-# If you want a smaller set of lints you can change this to specify
-# 'package:lints/core.yaml'. These are just the most critical lints
-# (the recommended set includes the core lints).
-# The core lints are also what is used by pub.dev for scoring packages.
-
-include: package:lints/recommended.yaml
-
-# Uncomment the following section to specify additional rules.
-
-# linter:
-# rules:
-# - camel_case_types
-
-# analyzer:
-# exclude:
-# - path/to/excluded/files/**
-
-# For more information about the core and recommended set of lints, see
-# https://dart.dev/go/core-lints
-
-# For additional information about configuring this file, see
-# https://dart.dev/guides/language/analysis-options
diff --git a/core/queue/lib/queue.dart b/core/queue/lib/queue.dart
deleted file mode 100644
index e69de29b..00000000
diff --git a/core/queue/lib/src/job_queued_event.dart b/core/queue/lib/src/job_queued_event.dart
deleted file mode 100644
index 5a55256b..00000000
--- a/core/queue/lib/src/job_queued_event.dart
+++ /dev/null
@@ -1,32 +0,0 @@
-import 'package:angel3_event_bus/event_bus.dart';
-import 'package:equatable/equatable.dart';
-
-class JobQueuedEvent extends AppEvent {
- final String connectionName;
- final String? queue;
- final dynamic jobId;
- final dynamic job;
- final String payload;
- final Duration? delay;
-
- JobQueuedEvent(this.connectionName, this.queue, this.jobId, this.job,
- this.payload, this.delay);
-
- @override
- List get props =>
- [connectionName, queue, jobId, job, payload, delay];
-
- @override
- Map toJson() {
- return {
- 'connectionName': connectionName,
- 'queue': queue,
- 'jobId': jobId,
- 'job': job.toString(), // or a more appropriate serialization of the job
- 'payload': payload,
- 'delay': delay?.inMilliseconds,
- };
- }
-
- String get name => 'job.queued';
-}
diff --git a/core/queue/lib/src/job_queueing_event.dart b/core/queue/lib/src/job_queueing_event.dart
deleted file mode 100644
index 44e2f626..00000000
--- a/core/queue/lib/src/job_queueing_event.dart
+++ /dev/null
@@ -1,29 +0,0 @@
-import 'package:angel3_event_bus/event_bus.dart';
-import 'package:equatable/equatable.dart';
-
-class JobQueueingEvent extends AppEvent {
- final String connectionName;
- final String? queue;
- final dynamic job;
- final String payload;
- final Duration? delay;
-
- JobQueueingEvent(
- this.connectionName, this.queue, this.job, this.payload, this.delay);
-
- @override
- List get props => [connectionName, queue, job, payload, delay];
-
- @override
- Map toJson() {
- return {
- 'connectionName': connectionName,
- 'queue': queue,
- 'job': job.toString(), // or a more appropriate serialization of the job
- 'payload': payload,
- 'delay': delay?.inMilliseconds,
- };
- }
-
- String get name => 'job.queueing';
-}
diff --git a/core/queue/lib/src/queue.dart b/core/queue/lib/src/queue.dart
deleted file mode 100644
index a87f752c..00000000
--- a/core/queue/lib/src/queue.dart
+++ /dev/null
@@ -1,396 +0,0 @@
-// lib/src/queue.dart
-
-import 'dart:async';
-import 'dart:convert';
-
-import 'package:angel3_container/angel3_container.dart';
-import 'package:angel3_event_bus/event_bus.dart';
-import 'package:angel3_mq/mq.dart';
-import 'package:angel3_reactivex/angel3_reactivex.dart';
-import 'package:crypto/crypto.dart';
-import 'package:uuid/uuid.dart';
-
-import 'job_queueing_event.dart';
-import 'job_queued_event.dart';
-import 'should_be_encrypted.dart';
-import 'should_queue_after_commit.dart';
-
-abstract class Queue with InteractsWithTime {
- /// The IoC container instance.
- final Container container;
- final EventBus eventBus;
- final MQClient mq;
- final Subject jobSubject;
- final Uuid uuid = Uuid();
-
- /// The connection name for the queue.
- String _connectionName;
-
- /// Indicates that jobs should be dispatched after all database transactions have committed.
- bool dispatchAfterCommit;
-
- /// The create payload callbacks.
- static final List _createPayloadCallbacks = [];
-
- Queue(this.container, this.eventBus, this.mq,
- {String connectionName = 'default', this.dispatchAfterCommit = false})
- : _connectionName = connectionName,
- jobSubject = PublishSubject() {
- _setupJobObservable();
- }
-
- void _setupJobObservable() {
- jobSubject.stream.listen((job) {
- // Process the job
- print('Processing job: $job');
- // Implement your job processing logic here
- });
- }
-
- Future pushOn(String queue, dynamic job, [dynamic data = '']) {
- return push(job, data, queue);
- }
-
- Future laterOn(String queue, Duration delay, dynamic job,
- [dynamic data = '']) {
- return later(delay, job, data, queue);
- }
-
- Future bulk(List jobs,
- [dynamic data = '', String? queue]) async {
- for (var job in jobs) {
- await push(job, data, queue);
- }
- }
-
- // Add this method
- void setContainer(Container container) {
- // This method might not be necessary in Dart, as we're using final for container
- // But we can implement it for API compatibility
- throw UnsupportedError(
- 'Container is final and cannot be changed after initialization');
- }
-
- // Update createPayload method to include exception handling
- Future createPayload(dynamic job, String queue,
- [dynamic data = '']) async {
- if (job is Function) {
- // TODO: Implement CallQueuedClosure equivalent
- throw UnimplementedError('Closure jobs are not yet supported');
- }
-
- try {
- final payload = jsonEncode(await createPayloadMap(job, queue, data));
- return payload;
- } catch (e) {
- throw InvalidPayloadException('Unable to JSON encode payload: $e');
- }
- }
-
- Future> createPayloadMap(dynamic job, String queue,
- [dynamic data = '']) async {
- if (job is Object) {
- return createObjectPayload(job, queue);
- } else {
- return createStringPayload(job.toString(), queue, data);
- }
- }
-
- Future> createObjectPayload(
- Object job, String queue) async {
- final payload = await withCreatePayloadHooks(queue, {
- 'uuid': const Uuid().v4(),
- 'displayName': getDisplayName(job),
- 'job': 'CallQueuedHandler@call', // TODO: Implement CallQueuedHandler
- 'maxTries': getJobTries(job),
- 'maxExceptions': job is HasMaxExceptions ? job.maxExceptions : null,
- 'failOnTimeout': job is HasFailOnTimeout ? job.failOnTimeout : false,
- 'backoff': getJobBackoff(job),
- 'timeout': job is HasTimeout ? job.timeout : null,
- 'retryUntil': getJobExpiration(job),
- 'data': {
- 'commandName': job.runtimeType.toString(),
- 'command': job,
- },
- });
-
- final command = jobShouldBeEncrypted(job) && container.has()
- ? container.make().encrypt(jsonEncode(job))
- : jsonEncode(job);
-
- payload['data'] = {
- ...payload['data'] as Map,
- 'commandName': job.runtimeType.toString(),
- 'command': command,
- };
-
- return payload;
- }
-
- String getDisplayName(Object job) {
- if (job is HasDisplayName) {
- return job.displayName();
- }
- return job.runtimeType.toString();
- }
-
- int? getJobTries(dynamic job) {
- if (job is HasTries) {
- return job.tries;
- }
- return null;
- }
-
- String? getJobBackoff(dynamic job) {
- if (job is HasBackoff) {
- final backoff = job.backoff;
- if (backoff == null) return null;
- if (backoff is Duration) {
- return backoff.inSeconds.toString();
- }
- if (backoff is List) {
- return backoff.map((d) => d.inSeconds).join(',');
- }
- }
- return null;
- }
-
- int? getJobExpiration(dynamic job) {
- if (job is HasRetryUntil) {
- final retryUntil = job.retryUntil;
- if (retryUntil == null) return null;
- return retryUntil.millisecondsSinceEpoch ~/ 1000;
- }
- return null;
- }
-
- bool jobShouldBeEncrypted(Object job) {
- return job is ShouldBeEncrypted ||
- (job is HasShouldBeEncrypted && job.shouldBeEncrypted);
- }
-
- Future> createStringPayload(
- String job, String queue, dynamic data) async {
- return withCreatePayloadHooks(queue, {
- 'uuid': const Uuid().v4(),
- 'displayName': job.split('@')[0],
- 'job': job,
- 'maxTries': null,
- 'maxExceptions': null,
- 'failOnTimeout': false,
- 'backoff': null,
- 'timeout': null,
- 'data': data,
- });
- }
-
- static void createPayloadUsing(Function? callback) {
- if (callback == null) {
- _createPayloadCallbacks.clear();
- } else {
- _createPayloadCallbacks.add(callback);
- }
- }
-
- Future> withCreatePayloadHooks(
- String queue, Map payload) async {
- if (_createPayloadCallbacks.isNotEmpty) {
- for (var callback in _createPayloadCallbacks) {
- final result = await callback(_connectionName, queue, payload);
- if (result is Map) {
- payload = {...payload, ...result};
- }
- }
- }
- return payload;
- }
-
- Future enqueueUsing(
- dynamic job,
- String payload,
- String? queue,
- Duration? delay,
- Future Function(String, String?, Duration?) callback,
- ) async {
- final String jobId = uuid.v4(); // Generate a unique job ID
-
- if (shouldDispatchAfterCommit(job) && container.has()) {
- return container.make().addCallback(() async {
- await raiseJobQueueingEvent(queue, job, payload, delay);
- final result = await callback(payload, queue, delay);
- await raiseJobQueuedEvent(queue, jobId, job, payload, delay);
- return result;
- });
- }
-
- await raiseJobQueueingEvent(queue, job, payload, delay);
- final result = await callback(payload, queue, delay);
- await raiseJobQueuedEvent(queue, jobId, job, payload, delay);
-
- // Use angel3_mq to publish the job
- mq.sendMessage(
- message: Message(
- headers: {'jobId': jobId}, // Include jobId in headers
- payload: payload,
- timestamp: DateTime.now().toIso8601String(),
- ),
- exchangeName: '', // Use default exchange
- routingKey: queue ?? 'default',
- );
-
- // Use angel3_reactivex to add the job to the subject
- jobSubject.add(job);
-
- return result;
- }
-
- bool shouldDispatchAfterCommit(dynamic job) {
- if (job is ShouldQueueAfterCommit) {
- return true;
- }
- if (job is HasAfterCommit) {
- return job.afterCommit;
- }
- return dispatchAfterCommit;
- }
-
- Future raiseJobQueueingEvent(
- String? queue, dynamic job, String payload, Duration? delay) async {
- if (container.has()) {
- final eventBus = container.make();
- eventBus
- .fire(JobQueueingEvent(_connectionName, queue, job, payload, delay));
- }
- }
-
- Future raiseJobQueuedEvent(String? queue, dynamic jobId, dynamic job,
- String payload, Duration? delay) async {
- if (container.has()) {
- final eventBus = container.make();
- eventBus.fire(
- JobQueuedEvent(_connectionName, queue, jobId, job, payload, delay));
- }
- }
-
- String get connectionName => _connectionName;
-
- set connectionName(String name) {
- _connectionName = name;
- }
-
- Container getContainer() => container;
-
- // Abstract methods to be implemented by subclasses
- // Implement the push method
- Future push(dynamic job, [dynamic data = '', String? queue]) async {
- final payload = await createPayload(job, queue ?? 'default', data);
- return enqueueUsing(job, payload, queue, null, (payload, queue, _) async {
- final jobId = Uuid().v4();
- mq.sendMessage(
- message: Message(
- id: jobId,
- headers: {},
- payload: payload,
- timestamp: DateTime.now().toIso8601String(),
- ),
- exchangeName: '',
- routingKey: queue ?? 'default',
- );
- return jobId;
- });
- }
-
- // Implement the later method
- Future later(Duration delay, dynamic job,
- [dynamic data = '', String? queue]) async {
- final payload = await createPayload(job, queue ?? 'default', data);
- return enqueueUsing(job, payload, queue, delay,
- (payload, queue, delay) async {
- final jobId = Uuid().v4();
- await Future.delayed(delay!);
- mq.sendMessage(
- message: Message(
- id: jobId,
- headers: {},
- payload: payload,
- timestamp: DateTime.now().toIso8601String(),
- ),
- exchangeName: '',
- routingKey: queue ?? 'default',
- );
- return jobId;
- });
- }
-
- // Cleanup method
- void dispose() {
- jobSubject.close();
- }
-}
-
-// Additional interfaces and classes
-
-abstract class HasMaxExceptions {
- int? get maxExceptions;
-}
-
-abstract class HasFailOnTimeout {
- bool get failOnTimeout;
-}
-
-abstract class HasTimeout {
- Duration? get timeout;
-}
-
-abstract class HasDisplayName {
- String displayName();
-}
-
-abstract class HasTries {
- int? get tries;
-}
-
-abstract class HasBackoff {
- dynamic get backoff;
-}
-
-abstract class HasRetryUntil {
- DateTime? get retryUntil;
-}
-
-abstract class HasAfterCommit {
- bool get afterCommit;
-}
-
-abstract class HasShouldBeEncrypted {
- bool get shouldBeEncrypted;
-}
-
-abstract class Encrypter {
- String encrypt(String data);
-}
-
-abstract class TransactionManager {
- Future addCallback(Future Function() callback);
-}
-
-// Add this mixin to the Queue class
-mixin InteractsWithTime {
- int secondsUntil(DateTime dateTime) {
- return dateTime.difference(DateTime.now()).inSeconds;
- }
-
- int availableAt(Duration delay) {
- return DateTime.now().add(delay).millisecondsSinceEpoch ~/ 1000;
- }
-}
-
-// First, define the InvalidPayloadException class
-class InvalidPayloadException implements Exception {
- final String message;
-
- InvalidPayloadException(this.message);
-
- @override
- String toString() => 'InvalidPayloadException: $message';
-}
diff --git a/core/queue/lib/src/should_be_encrypted.dart b/core/queue/lib/src/should_be_encrypted.dart
deleted file mode 100644
index 5db3ae8d..00000000
--- a/core/queue/lib/src/should_be_encrypted.dart
+++ /dev/null
@@ -1 +0,0 @@
-abstract class ShouldBeEncrypted {}
diff --git a/core/queue/lib/src/should_queue_after_commit.dart b/core/queue/lib/src/should_queue_after_commit.dart
deleted file mode 100644
index d00e3190..00000000
--- a/core/queue/lib/src/should_queue_after_commit.dart
+++ /dev/null
@@ -1 +0,0 @@
-abstract class ShouldQueueAfterCommit {}
diff --git a/core/queue/pubspec.yaml b/core/queue/pubspec.yaml
deleted file mode 100644
index 5083ecbd..00000000
--- a/core/queue/pubspec.yaml
+++ /dev/null
@@ -1,25 +0,0 @@
-name: angel3_queue
-description: The Queue Package for the Protevus Platform
-version: 0.0.1
-homepage: https://protevus.com
-documentation: https://docs.protevus.com
-repository: https://github.com/protevus/platformo
-
-environment:
- sdk: ^3.4.2
-
-# Add regular dependencies here.
-dependencies:
- angel3_container: ^8.0.0
- angel3_mq: ^8.0.0
- angel3_event_bus: ^8.0.0
- angel3_reactivex: ^8.0.0
- uuid: ^4.5.1
- crypto: ^3.0.5
-
-dev_dependencies:
- build_runner: ^2.3.3
- build_test: ^2.1.0
- lints: ^3.0.0
- mockito: ^5.0.0
- test: ^1.24.0
diff --git a/core/queue/test/queue_test.dart b/core/queue/test/queue_test.dart
deleted file mode 100644
index b8d811c0..00000000
--- a/core/queue/test/queue_test.dart
+++ /dev/null
@@ -1,317 +0,0 @@
-import 'package:test/test.dart';
-import 'package:mockito/annotations.dart';
-import 'package:mockito/mockito.dart';
-import 'package:angel3_container/angel3_container.dart';
-import 'package:angel3_event_bus/event_bus.dart';
-import 'package:angel3_mq/mq.dart';
-import 'package:angel3_queue/src/queue.dart';
-
-import 'package:angel3_queue/src/job_queueing_event.dart';
-import 'package:angel3_queue/src/job_queued_event.dart';
-import 'package:angel3_queue/src/should_queue_after_commit.dart';
-import 'queue_test.mocks.dart';
-
-@GenerateMocks([Container, MQClient, TransactionManager, Queue])
-void main() {
- late MockContainer container;
- late EventBus eventBus;
- late MockMQClient mq;
- late MockQueue queue;
- late List firedEvents;
-
- setUpAll(() {
- provideDummy(EventBus());
- });
-
- setUp(() {
- container = MockContainer();
- firedEvents = [];
- eventBus = EventBus();
- mq = MockMQClient();
- queue = MockQueue();
-
- // Inject the other mocks into the queue
- // queue.container = container;
- // queue.mq = mq;
-
- when(queue.container).thenReturn(container);
- when(queue.eventBus).thenReturn(eventBus);
- when(queue.mq).thenReturn(mq);
- when(queue.connectionName).thenReturn('default');
-
- // Stub for shouldDispatchAfterCommit
- when(queue.shouldDispatchAfterCommit(any)).thenReturn(false);
-
- // Modify the createPayload stub
- when(queue.createPayload(any, any, any)).thenAnswer((invocation) async {
- if (invocation.positionalArguments[0] is Map &&
- (invocation.positionalArguments[0] as Map).isEmpty) {
- throw InvalidPayloadException('Invalid job: empty map');
- }
- return 'valid payload';
- });
-
- // Modify the push stub
- when(queue.push(any, any, any)).thenAnswer((invocation) async {
- final job = invocation.positionalArguments[0];
- final data = invocation.positionalArguments[1];
- final queueName = invocation.positionalArguments[2];
- // Simulate firing events asynchronously
- Future.microtask(() {
- eventBus.fire(JobQueueingEvent(
- queue.connectionName, queueName, job, 'payload', null));
- eventBus.fire(JobQueuedEvent(
- queue.connectionName, queueName, 'job_id', job, 'payload', null));
- });
- return 'pushed';
- });
-
- // Stub for enqueueUsing
- when(queue.enqueueUsing(
- any,
- any,
- any,
- any,
- any,
- )).thenAnswer((invocation) async {
- final job = invocation.positionalArguments[0];
- final payload = invocation.positionalArguments[1];
- final queueName = invocation.positionalArguments[2];
- final delay = invocation.positionalArguments[3];
- final callback = invocation.positionalArguments[4] as Function;
-
- eventBus.fire(JobQueueingEvent(
- queue.connectionName, queueName, job, payload, delay));
- final result = await callback(payload, queueName, delay);
- eventBus.fire(JobQueuedEvent(
- queue.connectionName, queueName, result, job, payload, delay));
-
- return result;
- });
-
- // Stub for pushOn
- when(queue.pushOn(any, any, any)).thenAnswer((invocation) async {
- final queueName = invocation.positionalArguments[0];
- final job = invocation.positionalArguments[1];
- final data = invocation.positionalArguments[2];
- return queue.push(job, data, queueName);
- });
-
- // Modify the laterOn stub
- when(queue.laterOn(any, any, any, any)).thenAnswer((invocation) async {
- final queueName = invocation.positionalArguments[0];
- final delay = invocation.positionalArguments[1];
- final job = invocation.positionalArguments[2];
- final data = invocation.positionalArguments[3];
- // Directly return 'pushed later' instead of calling later
- return 'pushed later';
- });
-
- // Add a stub for bulk
- when(queue.bulk(any, any, any)).thenAnswer((invocation) async {
- final jobs = invocation.positionalArguments[0] as List;
- for (var job in jobs) {
- await queue.push(job, invocation.positionalArguments[1],
- invocation.positionalArguments[2]);
- }
- });
-
- // Stub for later
- when(queue.later(any, any, any, any)).thenAnswer((invocation) async {
- final delay = invocation.positionalArguments[0];
- final job = invocation.positionalArguments[1];
- final data = invocation.positionalArguments[2];
- final queueName = invocation.positionalArguments[3];
- final payload =
- await queue.createPayload(job, queueName ?? 'default', data);
- return queue.enqueueUsing(
- job, payload, queueName, delay, (p, q, d) async => 'delayed_job_id');
- });
-
- when(container.has()).thenReturn(true);
- when(container.has()).thenReturn(false);
- when(container.make()).thenReturn(eventBus);
-
- // Capture fired events
- eventBus.on().listen((event) {
- firedEvents.add(event);
- print("Debug: Event fired - ${event.runtimeType}");
- });
-
- // Setup for MQClient mock
- when(mq.sendMessage(
- message: anyNamed('message'),
- exchangeName: anyNamed('exchangeName'),
- routingKey: anyNamed('routingKey'),
- )).thenAnswer((_) {
- print("Debug: Mock sendMessage called");
- });
- });
-
- test('pushOn calls push with correct arguments', () async {
- final result = await queue.pushOn('test_queue', 'test_job', 'test_data');
- expect(result, equals('pushed'));
- verify(queue.push('test_job', 'test_data', 'test_queue')).called(1);
- });
-
- test('laterOn calls later with correct arguments', () async {
- final result = await queue.laterOn(
- 'test_queue', Duration(minutes: 5), 'test_job', 'test_data');
- expect(result, equals('pushed later'));
- // We're not actually calling 'later' in our stub, so we shouldn't verify it
- verify(queue.laterOn(
- 'test_queue', Duration(minutes: 5), 'test_job', 'test_data'))
- .called(1);
- });
-
- test('bulk pushes multiple jobs', () async {
- await queue.bulk(['job1', 'job2', 'job3'], 'test_data', 'test_queue');
- verify(queue.push('job1', 'test_data', 'test_queue')).called(1);
- verify(queue.push('job2', 'test_data', 'test_queue')).called(1);
- verify(queue.push('job3', 'test_data', 'test_queue')).called(1);
- });
-
- test('createPayload throws InvalidPayloadException for invalid job', () {
- expect(() => queue.createPayload({}, 'test_queue'),
- throwsA(isA()));
- });
- test('shouldDispatchAfterCommit returns correct value', () {
- when(queue.shouldDispatchAfterCommit(any)).thenReturn(false);
- expect(queue.shouldDispatchAfterCommit({}), isFalse);
-
- when(queue.shouldDispatchAfterCommit(any)).thenReturn(true);
- expect(queue.shouldDispatchAfterCommit({}), isTrue);
- });
-
- test('push enqueues job and fires events', () async {
- final job = 'test_job';
- final data = 'test_data';
- final queueName = 'test_queue';
-
- print("Debug: Before push");
- final result = await queue.push(job, data, queueName);
- print("Debug: After push");
-
- // Wait for all events to be processed
- await Future.delayed(Duration(milliseconds: 100));
-
- expect(result, equals('pushed'));
- verify(queue.push(job, data, queueName)).called(1);
-
- // Filter out EmptyEvents
- final significantEvents =
- firedEvents.where((event) => event is! EmptyEvent).toList();
-
- // Print fired events for debugging
- print("Fired events (excluding EmptyEvents):");
- for (var event in significantEvents) {
- print("${event.runtimeType}: ${event.toString()}");
- }
-
- // Verify fired events
- expect(significantEvents.where((event) => event is JobQueueingEvent).length,
- equals(1),
- reason: "JobQueueingEvent was not fired exactly once");
- expect(significantEvents.where((event) => event is JobQueuedEvent).length,
- equals(1),
- reason: "JobQueuedEvent was not fired exactly once");
- });
-}
-
-class TestQueue extends Queue {
- List pushedJobs = [];
-
- TestQueue(Container container, EventBus eventBus, MQClient mq)
- : super(container, eventBus, mq);
-
- @override
- Future push(dynamic job, [dynamic data = '', String? queue]) async {
- pushedJobs.add(job);
- final payload = await createPayload(job, queue ?? 'default', data);
- return enqueueUsing(job, payload, queue, null, (payload, queue, _) async {
- final jobId = 'test-job-id';
- mq.sendMessage(
- message: Message(
- id: jobId,
- headers: {},
- payload: payload,
- timestamp: DateTime.now().toIso8601String(),
- ),
- exchangeName: '',
- routingKey: queue ?? 'default',
- );
- return jobId;
- });
- }
-
- @override
- Future later(Duration delay, dynamic job,
- [dynamic data = '', String? queue]) async {
- return 'pushed later';
- }
-
- @override
- Future createPayload(dynamic job, String queue,
- [dynamic data = '']) async {
- if (job is Map && job.isEmpty) {
- throw InvalidPayloadException('Invalid job: empty map');
- }
- return 'valid payload';
- }
-
- @override
- bool shouldDispatchAfterCommit(dynamic job) {
- if (job is ShouldQueueAfterCommit) {
- return true;
- }
- return dispatchAfterCommit;
- }
-
- @override
- Future enqueueUsing(
- dynamic job,
- String payload,
- String? queue,
- Duration? delay,
- Future