add: adding contracts

This commit is contained in:
Patrick Stewart 2024-12-01 07:05:22 -07:00
parent 5c762c27e4
commit 629275b136
171 changed files with 4976 additions and 2410 deletions

View file

@ -2,4 +2,12 @@ mirrors.dart
/home/platform/Devboxes/sdk/sdk/lib/mirrors
mirrors.h mirrors.cc
/home/platform/Devboxes/sdk/runtime/lib
/home/platform/Devboxes/fake_reflection
/home/platform/Devboxes/fake_reflection
Abstract language agnostic specification in YAML
/home/platform/Devboxes/api/laravel
PHP reference implementation
/home/platform/Devboxes/resources/laravel_framework/src/Illuminate

View file

@ -1,71 +1,228 @@
/// Platform Contracts Library
/// Support contracts library
///
/// This library provides the core contracts (interfaces) that define
/// the Platform framework's API. These contracts ensure consistency
/// and interoperability between components while enabling loose coupling
/// and dependency injection.
/// This library provides a set of interfaces that define the core contracts
/// used throughout the framework. These contracts establish a standard way
/// of implementing common functionality like array conversion, JSON serialization,
/// HTML rendering, and HTTP response handling.
library contracts;
// Level 0: Core Foundation Contracts
// Auth contracts
export 'src/auth/auth_factory.dart';
export 'src/auth/authenticatable.dart';
export 'src/auth/can_reset_password.dart';
export 'src/auth/guard.dart';
export 'src/auth/must_verify_email.dart';
export 'src/auth/password_broker.dart';
export 'src/auth/password_broker_factory.dart';
export 'src/auth/stateful_guard.dart';
export 'src/auth/supports_basic_auth.dart';
export 'src/auth/user_provider.dart';
// Container contracts (from packages/container)
// Auth Access contracts
export 'src/auth/access/authorizable.dart';
export 'src/auth/access/authorization_exception.dart';
export 'src/auth/access/gate.dart';
// Auth Middleware contracts
export 'src/auth/middleware/authenticates_requests.dart';
// Broadcasting contracts
export 'src/broadcasting/broadcast_exception.dart';
export 'src/broadcasting/broadcast_factory.dart';
export 'src/broadcasting/broadcaster.dart';
export 'src/broadcasting/has_broadcast_channel.dart';
export 'src/broadcasting/should_be_unique.dart' show BroadcastShouldBeUnique;
export 'src/broadcasting/should_broadcast.dart';
export 'src/broadcasting/should_broadcast_now.dart';
// Bus contracts
export 'src/bus/dispatcher.dart' show BusDispatcher;
export 'src/bus/queueing_dispatcher.dart';
// Cache contracts
export 'src/cache/cache_factory.dart';
export 'src/cache/cache_interface.dart';
export 'src/cache/lock.dart';
export 'src/cache/lock_provider.dart';
export 'src/cache/lock_timeout_exception.dart' show CacheLockTimeoutException;
export 'src/cache/repository.dart';
export 'src/cache/store.dart';
// Config contracts
export 'src/config/repository.dart';
// Console contracts
export 'src/console/application.dart';
export 'src/console/isolatable.dart';
export 'src/console/kernel.dart';
export 'src/console/prompts_for_missing_input.dart';
// Container contracts
export 'src/container/binding_resolution_exception.dart';
export 'src/container/circular_dependency_exception.dart';
export 'src/container/container.dart';
export 'src/container/container_contract.dart';
export 'src/container/container_interface.dart';
export 'src/container/contextual_binding_contract.dart';
// Reflection contracts (from packages/container)
export 'src/reflection/reflection.dart';
// Cookie contracts
export 'src/cookie/cookie_factory.dart' show CookieFactory;
export 'src/cookie/queueing_factory.dart';
// Pipeline contracts (from packages/pipeline)
// Database contracts
export 'src/database/model_identifier.dart';
export 'src/database/query/builder.dart';
export 'src/database/query/expression.dart';
export 'src/database/query/condition_expression.dart';
// Database Eloquent contracts
export 'src/database/eloquent/builder.dart';
export 'src/database/eloquent/castable.dart';
export 'src/database/eloquent/casts_attributes.dart';
export 'src/database/eloquent/casts_inbound_attributes.dart';
export 'src/database/eloquent/deviates_castable_attributes.dart';
export 'src/database/eloquent/serializes_castable_attributes.dart';
export 'src/database/eloquent/supports_partial_relations.dart';
// Database Events contracts
export 'src/database/events/migration_event.dart';
// Debug contracts
export 'src/debug/exception_handler.dart';
// Encryption contracts
export 'src/encryption/decrypt_exception.dart';
export 'src/encryption/encrypt_exception.dart';
export 'src/encryption/encrypter.dart';
export 'src/encryption/string_encrypter.dart';
// Events contracts
export 'src/events/dispatcher.dart' show EventDispatcher;
export 'src/events/should_dispatch_after_commit.dart';
export 'src/events/should_handle_events_after_commit.dart';
// Filesystem contracts
export 'src/filesystem/cloud.dart';
export 'src/filesystem/file_not_found_exception.dart';
export 'src/filesystem/filesystem_factory.dart' show FilesystemFactory;
export 'src/filesystem/filesystem.dart';
export 'src/filesystem/lock_timeout_exception.dart'
show FilesystemLockTimeoutException;
// Foundation contracts
export 'src/foundation/application.dart';
export 'src/foundation/caches_configuration.dart';
export 'src/foundation/caches_routes.dart';
export 'src/foundation/exception_renderer.dart';
export 'src/foundation/maintenance_mode.dart';
// Hashing contracts
export 'src/hashing/hasher.dart';
// HTTP contracts
export 'src/http/kernel.dart';
export 'src/http/request.dart';
export 'src/http/response.dart';
// Mail contracts
export 'src/mail/attachable.dart';
export 'src/mail/mail_factory.dart' show MailFactory;
export 'src/mail/mailable.dart';
export 'src/mail/mail_queue.dart';
export 'src/mail/mailer.dart';
// Notifications contracts
export 'src/notifications/dispatcher.dart' show NotificationDispatcher;
export 'src/notifications/factory.dart';
// Pagination contracts
export 'src/pagination/cursor_paginator.dart';
export 'src/pagination/length_aware_paginator.dart';
export 'src/pagination/paginator.dart';
// Pipeline contracts
export 'src/pipeline/hub.dart';
export 'src/pipeline/pipeline.dart';
// Level 1: Infrastructure Contracts
// Process contracts
export 'src/process/invoked_process.dart';
export 'src/process/process_result.dart';
// Events contracts (from packages/events)
export 'src/events/events.dart';
// Bus contracts (from packages/bus)
export 'src/bus/bus.dart';
// Model contracts (from packages/model)
export 'src/model/model.dart';
// Process contracts (from packages/process)
export 'src/process/process.dart';
// Support contracts (from packages/support)
export 'src/support/support.dart';
// Level 2: Core Services Contracts
// Queue contracts (from packages/queue)
// Queue contracts
export 'src/queue/clearable_queue.dart';
export 'src/queue/entity_not_found_exception.dart';
export 'src/queue/entity_resolver.dart';
export 'src/queue/queue_factory.dart' show QueueFactory;
export 'src/queue/job.dart';
export 'src/queue/monitor.dart';
export 'src/queue/queue.dart';
export 'src/queue/queueable_collection.dart';
export 'src/queue/queueable_entity.dart';
export 'src/queue/should_be_encrypted.dart';
export 'src/queue/should_be_unique.dart' show QueueShouldBeUnique;
export 'src/queue/should_be_unique_until_processing.dart';
export 'src/queue/should_queue.dart';
export 'src/queue/should_queue_after_commit.dart';
// Level 3: HTTP Layer Contracts
// Redis contracts
export 'src/redis/connection.dart';
export 'src/redis/connector.dart';
export 'src/redis/redis_factory.dart' show RedisFactory;
export 'src/redis/limiter_timeout_exception.dart';
// Routing contracts (from packages/route)
export 'src/routing/routing.dart';
// Reflection contracts
export 'src/reflection/reflected_class.dart';
export 'src/reflection/reflected_function.dart';
export 'src/reflection/reflected_instance.dart';
export 'src/reflection/reflected_parameter.dart';
export 'src/reflection/reflected_type.dart';
export 'src/reflection/reflection.dart';
export 'src/reflection/reflector_contract.dart';
export 'src/reflection/reflector.dart';
// HTTP contracts (from packages/core)
export 'src/http/http.dart';
// Routing contracts
export 'src/routing/binding_registrar.dart';
export 'src/routing/registrar.dart';
export 'src/routing/response_factory.dart';
export 'src/routing/url_generator.dart';
export 'src/routing/url_routable.dart';
// Testing Contracts
// Session contracts
export 'src/session/session.dart';
export 'src/session/middleware/authenticates_sessions.dart';
// Testing contracts (from packages/testing)
export 'src/testing/testing.dart';
// Support contracts
export 'src/support/arrayable.dart';
export 'src/support/can_be_escaped_when_cast_to_string.dart';
export 'src/support/deferrable_provider.dart';
export 'src/support/deferring_displayable_value.dart';
export 'src/support/htmlable.dart';
export 'src/support/jsonable.dart';
export 'src/support/message_bag.dart';
export 'src/support/message_provider.dart';
export 'src/support/renderable.dart';
export 'src/support/responsable.dart';
export 'src/support/validated_data.dart';
// All contracts have been extracted from implemented packages:
// - Container & Reflection (Level 0)
// - Pipeline (Level 0)
// - Events (Level 1)
// - Bus (Level 1)
// - Model (Level 1)
// - Process (Level 1)
// - Support (Level 1)
// - Queue (Level 2)
// - Route (Level 3)
// - HTTP (Level 3)
// - Testing
// Translation contracts
export 'src/translation/has_locale_preference.dart';
export 'src/translation/loader.dart';
export 'src/translation/translator.dart';
// Next steps:
// 1. Update package dependencies to use these contracts
// 2. Implement contracts in each package
// 3. Add contract compliance tests
// 4. Document contract usage and patterns
// Validation contracts
export 'src/validation/data_aware_rule.dart';
export 'src/validation/validation_factory.dart' show ValidationFactory;
export 'src/validation/implicit_rule.dart';
export 'src/validation/invokable_rule.dart';
export 'src/validation/rule.dart';
export 'src/validation/uncompromised_verifier.dart';
export 'src/validation/validates_when_resolved.dart';
export 'src/validation/validation_rule.dart';
export 'src/validation/validator.dart';
export 'src/validation/validator_aware_rule.dart';
// View contracts
export 'src/view/engine.dart';
export 'src/view/view_factory.dart' show ViewFactory;
export 'src/view/view.dart';
export 'src/view/view_compilation_exception.dart';

View file

@ -0,0 +1,40 @@
/// Interface for authorization capabilities.
///
/// This contract defines how an entity can be checked for specific abilities
/// or permissions. It's typically implemented by user models to provide
/// authorization functionality.
abstract class Authorizable {
/// Determine if the entity has a given ability.
///
/// Example:
/// ```dart
/// class User implements Authorizable {
/// @override
/// Future<bool> can(dynamic abilities, [dynamic arguments = const []]) async {
/// if (abilities is String) {
/// // Check single ability
/// return await checkAbility(abilities, arguments);
/// } else if (abilities is Iterable) {
/// // Check multiple abilities
/// for (var ability in abilities) {
/// if (!await checkAbility(ability, arguments)) {
/// return false;
/// }
/// }
/// return true;
/// }
/// return false;
/// }
/// }
///
/// // Usage
/// if (await user.can('edit-post', post)) {
/// // User can edit the post
/// }
///
/// if (await user.can(['edit-post', 'delete-post'], post)) {
/// // User can both edit and delete the post
/// }
/// ```
Future<bool> can(dynamic abilities, [dynamic arguments = const []]);
}

View file

@ -0,0 +1,26 @@
/// Exception thrown when authorization fails.
///
/// This exception is thrown when an authorization check fails, typically
/// when a user attempts to perform an action they are not authorized to do.
class AuthorizationException implements Exception {
/// The message describing why authorization failed.
final String message;
/// The code associated with the authorization failure.
final String? code;
/// Create a new authorization exception.
///
/// Example:
/// ```dart
/// throw AuthorizationException(
/// 'User is not authorized to edit posts',
/// code: 'posts.edit.unauthorized',
/// );
/// ```
const AuthorizationException(this.message, {this.code});
@override
String toString() =>
'AuthorizationException: $message${code != null ? ' (code: $code)' : ''}';
}

View file

@ -0,0 +1,161 @@
/// Interface for authorization management.
///
/// This contract defines how authorization rules and policies should be managed
/// and checked. It provides methods for defining abilities, registering policies,
/// and performing authorization checks.
abstract class Gate {
/// Determine if a given ability has been defined.
///
/// Example:
/// ```dart
/// if (gate.has('edit-posts')) {
/// print('Edit posts ability is defined');
/// }
/// ```
bool has(String ability);
/// Define a new ability.
///
/// Example:
/// ```dart
/// gate.define('edit-post', (user, post) async {
/// return post.userId == user.id;
/// });
/// ```
Gate define(String ability, Function callback);
/// Define abilities for a resource.
///
/// Example:
/// ```dart
/// gate.resource('posts', Post, {
/// 'view': (user, post) async => true,
/// 'create': (user) async => user.isAdmin,
/// 'update': (user, post) async => post.userId == user.id,
/// 'delete': (user, post) async => user.isAdmin,
/// });
/// ```
Gate resource(String name, Type resourceClass,
[Map<String, Function>? abilities]);
/// Define a policy class for a given class type.
///
/// Example:
/// ```dart
/// gate.policy(Post, PostPolicy);
/// ```
Gate policy(Type class_, Type policy);
/// Register a callback to run before all Gate checks.
///
/// Example:
/// ```dart
/// gate.before((user, ability) {
/// if (user.isAdmin) return true;
/// });
/// ```
Gate before(Function callback);
/// Register a callback to run after all Gate checks.
///
/// Example:
/// ```dart
/// gate.after((user, ability, result, arguments) {
/// logAuthCheck(user, ability, result);
/// });
/// ```
Gate after(Function callback);
/// Determine if all of the given abilities should be granted for the current user.
///
/// Example:
/// ```dart
/// if (await gate.allows('edit-post', [post])) {
/// // User can edit the post
/// }
/// ```
Future<bool> allows(dynamic ability, [dynamic arguments = const []]);
/// Determine if any of the given abilities should be denied for the current user.
///
/// Example:
/// ```dart
/// if (await gate.denies('edit-post', [post])) {
/// // User cannot edit the post
/// }
/// ```
Future<bool> denies(dynamic ability, [dynamic arguments = const []]);
/// Determine if all of the given abilities should be granted for the current user.
///
/// Example:
/// ```dart
/// if (await gate.check(['edit-post', 'delete-post'], [post])) {
/// // User can both edit and delete the post
/// }
/// ```
Future<bool> check(dynamic abilities, [dynamic arguments = const []]);
/// Determine if any one of the given abilities should be granted for the current user.
///
/// Example:
/// ```dart
/// if (await gate.any(['edit-post', 'view-post'], [post])) {
/// // User can either edit or view the post
/// }
/// ```
Future<bool> any(dynamic abilities, [dynamic arguments = const []]);
/// Determine if the given ability should be granted for the current user.
///
/// Example:
/// ```dart
/// if (await gate.authorize('edit-post', [post])) {
/// // User is authorized to edit the post
/// }
/// ```
Future<bool> authorize(String ability, [dynamic arguments = const []]);
/// Inspect the user for the given ability.
///
/// Example:
/// ```dart
/// if (await gate.inspect('edit-post', [post])) {
/// // User has the ability to edit the post
/// }
/// ```
Future<bool> inspect(String ability, [dynamic arguments = const []]);
/// Get the raw result from the authorization callback.
///
/// Example:
/// ```dart
/// var result = await gate.raw('edit-post', [post]);
/// ```
Future<dynamic> raw(String ability, [dynamic arguments = const []]);
/// Get a policy instance for a given class.
///
/// Example:
/// ```dart
/// var policy = gate.getPolicyFor(Post);
/// ```
dynamic getPolicyFor(dynamic class_);
/// Get a gate instance for the given user.
///
/// Example:
/// ```dart
/// var userGate = gate.forUser(user);
/// ```
Gate forUser(dynamic user);
/// Get all of the defined abilities.
///
/// Example:
/// ```dart
/// var abilities = gate.abilities();
/// print('Defined abilities: ${abilities.keys.join(', ')}');
/// ```
Map<String, Function> abilities();
}

View file

@ -0,0 +1,28 @@
import 'guard.dart';
import 'stateful_guard.dart';
/// Interface for creating authentication guard instances.
///
/// This contract defines how authentication guards should be created and managed.
/// It provides methods for getting guard instances and setting the default guard.
abstract class AuthFactory {
/// Get a guard instance by name.
///
/// Example:
/// ```dart
/// // Get the default guard
/// var guard = factory.guard();
///
/// // Get a specific guard
/// var apiGuard = factory.guard('api');
/// ```
dynamic guard([String? name]);
/// Set the default guard the factory should serve.
///
/// Example:
/// ```dart
/// factory.shouldUse('web');
/// ```
void shouldUse(String name);
}

View file

@ -0,0 +1,84 @@
/// Interface for objects that can be authenticated.
///
/// This contract defines the methods that an authenticatable entity
/// (like a User model) must implement to work with the authentication system.
abstract class Authenticatable {
/// Get the name of the unique identifier for the user.
///
/// Example:
/// ```dart
/// class User implements Authenticatable {
/// @override
/// String getAuthIdentifierName() => 'id';
/// }
/// ```
String getAuthIdentifierName();
/// Get the unique identifier for the user.
///
/// Example:
/// ```dart
/// class User implements Authenticatable {
/// @override
/// dynamic getAuthIdentifier() => id;
/// }
/// ```
dynamic getAuthIdentifier();
/// Get the name of the password attribute for the user.
///
/// Example:
/// ```dart
/// class User implements Authenticatable {
/// @override
/// String getAuthPasswordName() => 'password';
/// }
/// ```
String getAuthPasswordName();
/// Get the password for the user.
///
/// Example:
/// ```dart
/// class User implements Authenticatable {
/// @override
/// String? getAuthPassword() => password;
/// }
/// ```
String? getAuthPassword();
/// Get the "remember me" token value.
///
/// Example:
/// ```dart
/// class User implements Authenticatable {
/// @override
/// String? getRememberToken() => rememberToken;
/// }
/// ```
String? getRememberToken();
/// Set the "remember me" token value.
///
/// Example:
/// ```dart
/// class User implements Authenticatable {
/// @override
/// void setRememberToken(String? value) {
/// rememberToken = value;
/// }
/// }
/// ```
void setRememberToken(String? value);
/// Get the column name for the "remember me" token.
///
/// Example:
/// ```dart
/// class User implements Authenticatable {
/// @override
/// String getRememberTokenName() => 'remember_token';
/// }
/// ```
String getRememberTokenName();
}

View file

@ -0,0 +1,35 @@
/// Interface for password reset functionality.
///
/// This contract defines how password reset functionality should be handled
/// for users that can reset their passwords. It provides methods for getting
/// the email address for password resets and sending reset notifications.
abstract class CanResetPassword {
/// Get the e-mail address where password reset links are sent.
///
/// Example:
/// ```dart
/// class User implements CanResetPassword {
/// @override
/// String getEmailForPasswordReset() => email;
/// }
/// ```
String getEmailForPasswordReset();
/// Send the password reset notification.
///
/// Example:
/// ```dart
/// class User implements CanResetPassword {
/// @override
/// Future<void> sendPasswordResetNotification(String token) async {
/// await notificationService.send(
/// PasswordResetNotification(
/// user: this,
/// token: token,
/// ),
/// );
/// }
/// }
/// ```
Future<void> sendPasswordResetNotification(String token);
}

View file

@ -0,0 +1,81 @@
import 'authenticatable.dart';
/// Interface for authentication guards.
///
/// This contract defines the methods that an authentication guard must implement
/// to provide user authentication functionality.
abstract class Guard {
/// Determine if the current user is authenticated.
///
/// Example:
/// ```dart
/// if (guard.check()) {
/// print('User is authenticated');
/// }
/// ```
bool check();
/// Determine if the current user is a guest.
///
/// Example:
/// ```dart
/// if (guard.guest()) {
/// print('User is not authenticated');
/// }
/// ```
bool guest();
/// Get the currently authenticated user.
///
/// Example:
/// ```dart
/// var user = guard.user();
/// if (user != null) {
/// print('Hello ${user.name}');
/// }
/// ```
Authenticatable? user();
/// Get the ID for the currently authenticated user.
///
/// Example:
/// ```dart
/// var userId = guard.id();
/// if (userId != null) {
/// print('User ID: $userId');
/// }
/// ```
dynamic id();
/// Validate a user's credentials.
///
/// Example:
/// ```dart
/// var credentials = {
/// 'email': 'user@example.com',
/// 'password': 'password123'
/// };
/// if (guard.validate(credentials)) {
/// print('Credentials are valid');
/// }
/// ```
bool validate([Map<String, dynamic> credentials = const {}]);
/// Determine if the guard has a user instance.
///
/// Example:
/// ```dart
/// if (guard.hasUser()) {
/// print('Guard has a user instance');
/// }
/// ```
bool hasUser();
/// Set the current user.
///
/// Example:
/// ```dart
/// guard.setUser(user);
/// ```
Guard setUser(Authenticatable user);
}

View file

@ -0,0 +1,6 @@
/// Interface for middleware that authenticates requests.
///
/// This contract serves as a marker interface for middleware that handles
/// authentication of incoming requests. While it doesn't define any methods,
/// it provides a way to identify middleware that performs authentication.
abstract class AuthenticatesRequests {}

View file

@ -0,0 +1,60 @@
/// Interface for email verification functionality.
///
/// This contract defines how email verification should be handled for users
/// that require email verification. It provides methods for checking and
/// updating verification status, as well as sending verification notifications.
abstract class MustVerifyEmail {
/// Determine if the user has verified their email address.
///
/// Example:
/// ```dart
/// class User implements MustVerifyEmail {
/// @override
/// bool hasVerifiedEmail() {
/// return emailVerifiedAt != null;
/// }
/// }
/// ```
bool hasVerifiedEmail();
/// Mark the given user's email as verified.
///
/// Example:
/// ```dart
/// class User implements MustVerifyEmail {
/// @override
/// Future<bool> markEmailAsVerified() async {
/// emailVerifiedAt = DateTime.now();
/// await save();
/// return true;
/// }
/// }
/// ```
Future<bool> markEmailAsVerified();
/// Send the email verification notification.
///
/// Example:
/// ```dart
/// class User implements MustVerifyEmail {
/// @override
/// Future<void> sendEmailVerificationNotification() async {
/// await notificationService.send(
/// EmailVerificationNotification(user: this),
/// );
/// }
/// }
/// ```
Future<void> sendEmailVerificationNotification();
/// Get the email address that should be used for verification.
///
/// Example:
/// ```dart
/// class User implements MustVerifyEmail {
/// @override
/// String getEmailForVerification() => email;
/// }
/// ```
String getEmailForVerification();
}

View file

@ -0,0 +1,69 @@
/// Interface for password reset functionality.
///
/// This contract defines how password reset operations should be handled,
/// including sending reset links and performing password resets.
abstract class PasswordBroker {
/// Constant representing a successfully sent reminder.
static const String resetLinkSent = 'passwords.sent';
/// Constant representing a successfully reset password.
static const String passwordReset = 'passwords.reset';
/// Constant representing the user not found response.
static const String invalidUser = 'passwords.user';
/// Constant representing an invalid token.
static const String invalidToken = 'passwords.token';
/// Constant representing a throttled reset attempt.
static const String resetThrottled = 'passwords.throttled';
/// Send a password reset link to a user.
///
/// Example:
/// ```dart
/// var credentials = {'email': 'user@example.com'};
/// var status = await broker.sendResetLink(
/// credentials,
/// (user) async {
/// // Custom notification logic
/// },
/// );
///
/// if (status == PasswordBroker.resetLinkSent) {
/// // Reset link was sent successfully
/// }
/// ```
Future<String> sendResetLink(
Map<String, dynamic> credentials, [
void Function(dynamic user)? callback,
]);
/// Reset the password for the given token.
///
/// Example:
/// ```dart
/// var credentials = {
/// 'email': 'user@example.com',
/// 'password': 'newpassword',
/// 'token': 'reset-token'
/// };
///
/// var status = await broker.reset(
/// credentials,
/// (user) async {
/// // Set the new password
/// await user.setPassword(credentials['password']);
/// await user.save();
/// },
/// );
///
/// if (status == PasswordBroker.passwordReset) {
/// // Password was reset successfully
/// }
/// ```
Future<String> reset(
Map<String, dynamic> credentials,
void Function(dynamic user) callback,
);
}

View file

@ -0,0 +1,23 @@
import 'password_broker.dart';
/// Interface for creating password broker instances.
///
/// This contract defines how password broker instances should be created
/// and managed, allowing for multiple password broker configurations.
abstract class PasswordBrokerFactory {
/// Get a password broker instance by name.
///
/// Example:
/// ```dart
/// // Get the default broker
/// var broker = factory.broker();
///
/// // Get a specific broker
/// var adminBroker = factory.broker('admins');
///
/// var status = await broker.sendResetLink({
/// 'email': 'user@example.com'
/// });
/// ```
PasswordBroker broker([String? name]);
}

View file

@ -0,0 +1,88 @@
import 'authenticatable.dart';
import 'guard.dart';
/// Interface for stateful authentication guards.
///
/// This contract extends the base Guard interface to add methods for
/// maintaining authentication state, such as login/logout functionality
/// and "remember me" capabilities.
abstract class StatefulGuard implements Guard {
/// Attempt to authenticate a user using the given credentials.
///
/// Example:
/// ```dart
/// var credentials = {
/// 'email': 'user@example.com',
/// 'password': 'password123'
/// };
/// if (await guard.attempt(credentials, remember: true)) {
/// // User is authenticated and will be remembered
/// }
/// ```
Future<bool> attempt([
Map<String, dynamic> credentials = const {},
bool remember = false,
]);
/// Log a user into the application without sessions or cookies.
///
/// Example:
/// ```dart
/// var credentials = {
/// 'email': 'user@example.com',
/// 'password': 'password123'
/// };
/// if (await guard.once(credentials)) {
/// // User is authenticated for this request only
/// }
/// ```
Future<bool> once([Map<String, dynamic> credentials = const {}]);
/// Log a user into the application.
///
/// Example:
/// ```dart
/// await guard.login(user, remember: true);
/// ```
Future<void> login(Authenticatable user, [bool remember = false]);
/// Log the given user ID into the application.
///
/// Example:
/// ```dart
/// var user = await guard.loginUsingId(1, remember: true);
/// if (user != null) {
/// // User was logged in successfully
/// }
/// ```
Future<Authenticatable?> loginUsingId(dynamic id, [bool remember = false]);
/// Log the given user ID into the application without sessions or cookies.
///
/// Example:
/// ```dart
/// var user = await guard.onceUsingId(1);
/// if (user != null) {
/// // User was logged in for this request only
/// }
/// ```
Future<Authenticatable?> onceUsingId(dynamic id);
/// Determine if the user was authenticated via "remember me" cookie.
///
/// Example:
/// ```dart
/// if (guard.viaRemember()) {
/// // User was authenticated using remember me cookie
/// }
/// ```
bool viaRemember();
/// Log the user out of the application.
///
/// Example:
/// ```dart
/// await guard.logout();
/// ```
Future<void> logout();
}

View file

@ -0,0 +1,65 @@
import '../http/response.dart';
/// Interface for HTTP Basic Authentication support.
///
/// This contract defines how HTTP Basic Authentication should be handled,
/// providing methods for both stateful and stateless authentication attempts.
abstract class SupportsBasicAuth {
/// Attempt to authenticate using HTTP Basic Auth.
///
/// Example:
/// ```dart
/// class ApiGuard implements SupportsBasicAuth {
/// @override
/// Future<Response?> basic([
/// String field = 'email',
/// Map<String, dynamic> extraConditions = const {},
/// ]) async {
/// var credentials = getBasicAuthCredentials();
/// if (await validateCredentials(credentials)) {
/// return null; // Authentication successful
/// }
/// return Response(
/// content: 'Unauthorized',
/// status: 401,
/// headers: {
/// 'WWW-Authenticate': 'Basic realm="API Access"'
/// },
/// );
/// }
/// }
/// ```
Future<Response?> basic([
String field = 'email',
Map<String, dynamic> extraConditions = const {},
]);
/// Perform a stateless HTTP Basic login attempt.
///
/// Example:
/// ```dart
/// class ApiGuard implements SupportsBasicAuth {
/// @override
/// Future<Response?> onceBasic([
/// String field = 'email',
/// Map<String, dynamic> extraConditions = const {},
/// ]) async {
/// var credentials = getBasicAuthCredentials();
/// if (await validateCredentials(credentials)) {
/// return null; // Authentication successful
/// }
/// return Response(
/// content: 'Unauthorized',
/// status: 401,
/// headers: {
/// 'WWW-Authenticate': 'Basic realm="API Access"'
/// },
/// );
/// }
/// }
/// ```
Future<Response?> onceBasic([
String field = 'email',
Map<String, dynamic> extraConditions = const {},
]);
}

View file

@ -0,0 +1,86 @@
import 'authenticatable.dart';
/// Interface for retrieving and validating users.
///
/// This contract defines how users should be retrieved from storage
/// and how their credentials should be validated.
abstract class UserProvider {
/// Retrieve a user by their unique identifier.
///
/// Example:
/// ```dart
/// var user = await provider.retrieveById(1);
/// if (user != null) {
/// print('Found user: ${user.getAuthIdentifier()}');
/// }
/// ```
Future<Authenticatable?> retrieveById(dynamic identifier);
/// Retrieve a user by their unique identifier and "remember me" token.
///
/// Example:
/// ```dart
/// var user = await provider.retrieveByToken(1, 'remember-token');
/// if (user != null) {
/// print('Found user by remember token');
/// }
/// ```
Future<Authenticatable?> retrieveByToken(dynamic identifier, String token);
/// Update the "remember me" token for the given user in storage.
///
/// Example:
/// ```dart
/// await provider.updateRememberToken(user, 'new-remember-token');
/// ```
Future<void> updateRememberToken(Authenticatable user, String token);
/// Retrieve a user by the given credentials.
///
/// Example:
/// ```dart
/// var credentials = {
/// 'email': 'user@example.com',
/// 'password': 'password123'
/// };
/// var user = await provider.retrieveByCredentials(credentials);
/// if (user != null) {
/// print('Found user by credentials');
/// }
/// ```
Future<Authenticatable?> retrieveByCredentials(
Map<String, dynamic> credentials);
/// Validate a user against the given credentials.
///
/// Example:
/// ```dart
/// var credentials = {
/// 'email': 'user@example.com',
/// 'password': 'password123'
/// };
/// if (await provider.validateCredentials(user, credentials)) {
/// print('Credentials are valid');
/// }
/// ```
Future<bool> validateCredentials(
Authenticatable user,
Map<String, dynamic> credentials,
);
/// Rehash the user's password if required and supported.
///
/// Example:
/// ```dart
/// await provider.rehashPasswordIfRequired(
/// user,
/// credentials,
/// force: true,
/// );
/// ```
Future<void> rehashPasswordIfRequired(
Authenticatable user,
Map<String, dynamic> credentials, [
bool force = false,
]);
}

View file

@ -0,0 +1,19 @@
/// Exception thrown when broadcasting fails.
///
/// This exception is thrown when there is an error during broadcasting,
/// such as connection issues or invalid channel configurations.
class BroadcastException implements Exception {
/// The message describing why broadcasting failed.
final String message;
/// Create a new broadcast exception.
///
/// Example:
/// ```dart
/// throw BroadcastException('Failed to connect to broadcasting server');
/// ```
const BroadcastException(this.message);
@override
String toString() => 'BroadcastException: $message';
}

View file

@ -0,0 +1,19 @@
import 'broadcaster.dart';
/// Interface for creating broadcaster instances.
///
/// This contract defines how broadcaster instances should be created and managed.
/// It provides methods for getting broadcaster instances by name.
abstract class BroadcastFactory {
/// Get a broadcaster implementation by name.
///
/// Example:
/// ```dart
/// // Get the default broadcaster
/// var broadcaster = factory.connection();
///
/// // Get a specific broadcaster
/// var pusherBroadcaster = factory.connection('pusher');
/// ```
Future<Broadcaster> connection([String? name]);
}

View file

@ -0,0 +1,48 @@
import '../http/request.dart';
import 'broadcast_exception.dart';
/// Interface for broadcasting functionality.
///
/// This contract defines how broadcasting should be handled,
/// providing methods for authentication and event broadcasting.
abstract class Broadcaster {
/// Authenticate the incoming request for a given channel.
///
/// Example:
/// ```dart
/// var result = await broadcaster.auth(request);
/// if (result != null) {
/// // Request is authenticated
/// }
/// ```
Future<dynamic> auth(Request request);
/// Return the valid authentication response.
///
/// Example:
/// ```dart
/// var response = await broadcaster.validAuthenticationResponse(
/// request,
/// authResult,
/// );
/// ```
Future<dynamic> validAuthenticationResponse(Request request, dynamic result);
/// Broadcast the given event.
///
/// Example:
/// ```dart
/// await broadcaster.broadcast(
/// ['private-orders.1', 'private-orders.2'],
/// 'OrderShipped',
/// {'orderId': 1},
/// );
/// ```
///
/// Throws a [BroadcastException] if broadcasting fails.
Future<void> broadcast(
List<String> channels,
String event, [
Map<String, dynamic> payload = const {},
]);
}

View file

@ -0,0 +1,40 @@
/// Interface for entities that have associated broadcast channels.
///
/// This contract defines how entities should specify their broadcast channel
/// route definitions and names. It's typically implemented by models that
/// need to be associated with specific broadcast channels.
abstract class HasBroadcastChannel {
/// Get the broadcast channel route definition associated with the entity.
///
/// Example:
/// ```dart
/// class Order implements HasBroadcastChannel {
/// final int id;
///
/// Order(this.id);
///
/// @override
/// String broadcastChannelRoute() {
/// return 'orders.{order}';
/// }
/// }
/// ```
String broadcastChannelRoute();
/// Get the broadcast channel name associated with the entity.
///
/// Example:
/// ```dart
/// class Order implements HasBroadcastChannel {
/// final int id;
///
/// Order(this.id);
///
/// @override
/// String broadcastChannel() {
/// return 'orders.$id';
/// }
/// }
/// ```
String broadcastChannel();
}

View file

@ -0,0 +1,21 @@
/// Interface for broadcasts that should be unique.
///
/// This contract serves as a marker interface for broadcasts that should
/// be unique. While it doesn't define any methods, implementing this interface
/// signals that the broadcast should be unique and any duplicate broadcasts
/// should be prevented.
///
/// Example:
/// ```dart
/// class OrderShippedEvent implements ShouldBroadcast, ShouldBeUnique {
/// final int orderId;
///
/// OrderShippedEvent(this.orderId);
///
/// @override
/// dynamic broadcastOn() {
/// return 'orders.$orderId';
/// }
/// }
/// ```
abstract class ShouldBeUnique {}

View file

@ -0,0 +1,29 @@
/// Interface for events that should be broadcast.
///
/// This contract defines how events should specify their broadcast channels.
/// It's implemented by event classes that need to be broadcast to specific channels.
abstract class ShouldBroadcast {
/// Get the channels the event should broadcast on.
///
/// Example:
/// ```dart
/// class OrderShippedEvent implements ShouldBroadcast {
/// final int orderId;
///
/// OrderShippedEvent(this.orderId);
///
/// @override
/// dynamic broadcastOn() {
/// // Return a single channel
/// return 'orders.$orderId';
///
/// // Or return multiple channels
/// return [
/// 'orders.$orderId',
/// 'admin.orders',
/// ];
/// }
/// }
/// ```
dynamic broadcastOn();
}

View file

@ -0,0 +1,23 @@
import 'should_broadcast.dart';
/// Interface for events that should be broadcast immediately.
///
/// This contract extends [ShouldBroadcast] and serves as a marker interface
/// for events that should be broadcast immediately rather than being queued.
/// While it doesn't define any additional methods, implementing this interface
/// signals that the event should bypass the queue.
///
/// Example:
/// ```dart
/// class OrderShippedEvent implements ShouldBroadcastNow {
/// final int orderId;
///
/// OrderShippedEvent(this.orderId);
///
/// @override
/// dynamic broadcastOn() {
/// return 'orders.$orderId';
/// }
/// }
/// ```
abstract class ShouldBroadcastNow implements ShouldBroadcast {}

View file

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

View file

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

View file

@ -0,0 +1,81 @@
/// Interface for command bus dispatching.
///
/// This contract defines how commands should be dispatched to their handlers.
/// It provides methods for both synchronous and asynchronous command handling,
/// as well as configuration of command handling pipelines.
abstract class Dispatcher {
/// Dispatch a command to its appropriate handler.
///
/// Example:
/// ```dart
/// var result = await dispatcher.dispatch(
/// CreateOrderCommand(items: items),
/// );
/// ```
Future<dynamic> dispatch(dynamic command);
/// Dispatch a command to its appropriate handler in the current process.
///
/// Queueable jobs will be dispatched to the "sync" queue.
///
/// Example:
/// ```dart
/// var result = await dispatcher.dispatchSync(
/// CreateOrderCommand(items: items),
/// );
/// ```
Future<dynamic> dispatchSync(dynamic command, [dynamic handler]);
/// Dispatch a command to its appropriate handler in the current process.
///
/// Example:
/// ```dart
/// var result = await dispatcher.dispatchNow(
/// CreateOrderCommand(items: items),
/// );
/// ```
Future<dynamic> dispatchNow(dynamic command, [dynamic handler]);
/// Determine if the given command has a handler.
///
/// Example:
/// ```dart
/// if (dispatcher.hasCommandHandler(command)) {
/// print('Handler exists for command');
/// }
/// ```
bool hasCommandHandler(dynamic command);
/// Retrieve the handler for a command.
///
/// Example:
/// ```dart
/// var handler = dispatcher.getCommandHandler(command);
/// if (handler != null) {
/// print('Found handler: ${handler.runtimeType}');
/// }
/// ```
dynamic getCommandHandler(dynamic command);
/// Set the pipes commands should be piped through before dispatching.
///
/// Example:
/// ```dart
/// dispatcher.pipeThrough([
/// TransactionPipe(),
/// LoggingPipe(),
/// ]);
/// ```
Dispatcher pipeThrough(List<dynamic> pipes);
/// Map a command to a handler.
///
/// Example:
/// ```dart
/// dispatcher.map({
/// CreateOrderCommand: CreateOrderHandler,
/// UpdateOrderCommand: UpdateOrderHandler,
/// });
/// ```
Dispatcher map(Map<dynamic, dynamic> commandMap);
}

View file

@ -0,0 +1,40 @@
import 'dispatcher.dart';
/// Interface for queueing command bus dispatching.
///
/// This contract extends the base [Dispatcher] to add queueing functionality,
/// allowing commands to be dispatched to queues and processed in batches.
abstract class QueueingDispatcher implements Dispatcher {
/// Attempt to find the batch with the given ID.
///
/// Example:
/// ```dart
/// var batch = await dispatcher.findBatch('batch-123');
/// if (batch != null) {
/// print('Found batch with ${batch.jobs.length} jobs');
/// }
/// ```
Future<dynamic> findBatch(String batchId);
/// Create a new batch of queueable jobs.
///
/// Example:
/// ```dart
/// var batch = await dispatcher.batch([
/// ProcessOrderCommand(orderId: 1),
/// ProcessOrderCommand(orderId: 2),
/// ProcessOrderCommand(orderId: 3),
/// ]);
/// ```
Future<dynamic> batch(dynamic jobs);
/// Dispatch a command to its appropriate handler behind a queue.
///
/// Example:
/// ```dart
/// await dispatcher.dispatchToQueue(
/// ProcessLargeOrderCommand(orderId: 1),
/// );
/// ```
Future<dynamic> dispatchToQueue(dynamic command);
}

View file

@ -0,0 +1,19 @@
import 'repository.dart';
/// Interface for creating cache store instances.
///
/// This contract defines how cache store instances should be created and managed.
/// It provides methods for getting cache store instances by name.
abstract class CacheFactory {
/// Get a cache store instance by name.
///
/// Example:
/// ```dart
/// // Get the default store
/// var store = factory.store();
///
/// // Get a specific store
/// var redisStore = factory.store('redis');
/// ```
Future<CacheRepository> store([String? name]);
}

View file

@ -0,0 +1,75 @@
/// PSR-16 Cache Interface.
///
/// This is a Dart implementation of the PSR-16 CacheInterface.
/// It provides a simple caching interface for storing and retrieving values
/// by key.
abstract class CacheInterface {
/// Fetches a value from the cache.
///
/// Example:
/// ```dart
/// var value = await cache.get('key', defaultValue: 'default');
/// ```
Future<T?> get<T>(String key, {T? defaultValue});
/// Persists data in the cache, uniquely referenced by a key.
///
/// Example:
/// ```dart
/// await cache.set('key', 'value', ttl: Duration(minutes: 10));
/// ```
Future<bool> set(String key, dynamic value, {Duration? ttl});
/// Delete an item from the cache by its unique key.
///
/// Example:
/// ```dart
/// await cache.delete('key');
/// ```
Future<bool> delete(String key);
/// Wipes clean the entire cache's keys.
///
/// Example:
/// ```dart
/// await cache.clear();
/// ```
Future<bool> clear();
/// Obtains multiple cache items by their unique keys.
///
/// Example:
/// ```dart
/// var values = await cache.getMultiple(['key1', 'key2']);
/// ```
Future<Map<String, T?>> getMultiple<T>(Iterable<String> keys);
/// Persists a set of key => value pairs in the cache.
///
/// Example:
/// ```dart
/// await cache.setMultiple({
/// 'key1': 'value1',
/// 'key2': 'value2',
/// });
/// ```
Future<bool> setMultiple(Map<String, dynamic> values, {Duration? ttl});
/// Deletes multiple cache items in a single operation.
///
/// Example:
/// ```dart
/// await cache.deleteMultiple(['key1', 'key2']);
/// ```
Future<bool> deleteMultiple(Iterable<String> keys);
/// Determines whether an item is present in the cache.
///
/// Example:
/// ```dart
/// if (await cache.has('key')) {
/// print('Cache has key');
/// }
/// ```
Future<bool> has(String key);
}

View file

@ -0,0 +1,45 @@
/// Interface for cache locks.
///
/// This contract defines how cache locks should behave, providing methods
/// for acquiring, releasing, and managing locks.
abstract class Lock {
/// Attempt to acquire the lock.
///
/// Example:
/// ```dart
/// if (await lock.acquire()) {
/// try {
/// // Process that requires locking
/// } finally {
/// await lock.release();
/// }
/// }
/// ```
Future<bool> acquire();
/// Release the lock.
///
/// Example:
/// ```dart
/// await lock.release();
/// ```
Future<bool> release();
/// Get the owner value of the lock.
///
/// Example:
/// ```dart
/// var owner = lock.owner();
/// ```
String? owner();
/// Attempt to acquire the lock for the given number of seconds.
///
/// Example:
/// ```dart
/// if (await lock.block(5)) {
/// // Lock was acquired
/// }
/// ```
Future<bool> block(int seconds);
}

View file

@ -0,0 +1,30 @@
import 'lock.dart';
/// Interface for creating lock instances.
///
/// This contract defines how lock instances should be created and restored,
/// providing methods for getting new locks and restoring existing ones.
abstract class LockProvider {
/// Get a lock instance.
///
/// Example:
/// ```dart
/// var lock = provider.lock(
/// 'processing-order-1',
/// seconds: 60,
/// owner: 'worker-1',
/// );
/// ```
Lock lock(String name, {int seconds = 0, String? owner});
/// Restore a lock instance using the owner identifier.
///
/// Example:
/// ```dart
/// var lock = provider.restoreLock(
/// 'processing-order-1',
/// 'worker-1',
/// );
/// ```
Lock restoreLock(String name, String owner);
}

View file

@ -0,0 +1,19 @@
/// Exception thrown when a lock operation times out.
///
/// This exception is thrown when attempting to acquire a lock that could not
/// be obtained within the specified timeout period.
class LockTimeoutException implements Exception {
/// The message describing why the lock operation timed out.
final String message;
/// Create a new lock timeout exception.
///
/// Example:
/// ```dart
/// throw LockTimeoutException('Could not acquire lock "users" within 5 seconds');
/// ```
const LockTimeoutException(this.message);
@override
String toString() => 'LockTimeoutException: $message';
}

View file

@ -0,0 +1,110 @@
import 'cache_interface.dart';
import 'store.dart';
/// Interface for cache operations.
///
/// This contract extends the PSR-16 CacheInterface to add additional
/// functionality specific to Laravel's caching system.
abstract class CacheRepository extends CacheInterface {
/// Retrieve an item from the cache and delete it.
///
/// Example:
/// ```dart
/// var value = await cache.pull('key', defaultValue: 'default');
/// ```
Future<T> pull<T>(String key, {T? defaultValue});
/// Store an item in the cache.
///
/// Example:
/// ```dart
/// await cache.put('key', 'value', ttl: Duration(minutes: 10));
/// ```
Future<bool> put(String key, dynamic value, {Duration? ttl});
/// Store an item in the cache if the key does not exist.
///
/// Example:
/// ```dart
/// var added = await cache.add('key', 'value', ttl: Duration(minutes: 10));
/// ```
Future<bool> add(String key, dynamic value, {Duration? ttl});
/// Increment the value of an item in the cache.
///
/// Example:
/// ```dart
/// var newValue = await cache.increment('visits');
/// ```
Future<int?> increment(String key, [int value = 1]);
/// Decrement the value of an item in the cache.
///
/// Example:
/// ```dart
/// var newValue = await cache.decrement('remaining');
/// ```
Future<int?> decrement(String key, [int value = 1]);
/// Store an item in the cache indefinitely.
///
/// Example:
/// ```dart
/// await cache.forever('key', 'value');
/// ```
Future<bool> forever(String key, dynamic value);
/// Get an item from the cache, or execute the callback and store the result.
///
/// Example:
/// ```dart
/// var value = await cache.remember<String>(
/// 'key',
/// Duration(minutes: 10),
/// () async => await computeValue(),
/// );
/// ```
Future<T> remember<T>(
String key,
Duration? ttl,
Future<T> Function() callback,
);
/// Get an item from the cache, or execute the callback and store the result forever.
///
/// Example:
/// ```dart
/// var value = await cache.sear<String>(
/// 'key',
/// () async => await computeValue(),
/// );
/// ```
Future<T> sear<T>(String key, Future<T> Function() callback);
/// Get an item from the cache, or execute the callback and store the result forever.
///
/// Example:
/// ```dart
/// var value = await cache.rememberForever<String>(
/// 'key',
/// () async => await computeValue(),
/// );
/// ```
Future<T> rememberForever<T>(String key, Future<T> Function() callback);
/// Remove an item from the cache.
///
/// Example:
/// ```dart
/// await cache.forget('key');
/// ```
Future<bool> forget(String key);
/// Get the cache store implementation.
///
/// Example:
/// ```dart
/// var store = cache.getStore();
/// ```
CacheStore getStore();
}

View file

@ -0,0 +1,91 @@
/// Interface for cache store implementations.
///
/// This contract defines how cache stores should handle low-level cache operations.
/// It provides methods for storing, retrieving, and managing cached items at the
/// storage level.
abstract class CacheStore {
/// Retrieve an item from the cache by key.
///
/// Example:
/// ```dart
/// var value = await store.get('key');
/// ```
Future<dynamic> get(String key);
/// Retrieve multiple items from the cache by key.
///
/// Items not found in the cache will have a null value.
///
/// Example:
/// ```dart
/// var values = await store.many(['key1', 'key2']);
/// ```
Future<Map<String, dynamic>> many(List<String> keys);
/// Store an item in the cache for a given number of seconds.
///
/// Example:
/// ```dart
/// await store.put('key', 'value', 600); // 10 minutes
/// ```
Future<bool> put(String key, dynamic value, int seconds);
/// Store multiple items in the cache for a given number of seconds.
///
/// Example:
/// ```dart
/// await store.putMany({
/// 'key1': 'value1',
/// 'key2': 'value2',
/// }, 600); // 10 minutes
/// ```
Future<bool> putMany(Map<String, dynamic> values, int seconds);
/// Increment the value of an item in the cache.
///
/// Example:
/// ```dart
/// var newValue = await store.increment('visits');
/// ```
Future<int?> increment(String key, [int value = 1]);
/// Decrement the value of an item in the cache.
///
/// Example:
/// ```dart
/// var newValue = await store.decrement('remaining');
/// ```
Future<int?> decrement(String key, [int value = 1]);
/// Store an item in the cache indefinitely.
///
/// Example:
/// ```dart
/// await store.forever('key', 'value');
/// ```
Future<bool> forever(String key, dynamic value);
/// Remove an item from the cache.
///
/// Example:
/// ```dart
/// await store.forget('key');
/// ```
Future<bool> forget(String key);
/// Remove all items from the cache.
///
/// Example:
/// ```dart
/// await store.flush();
/// ```
Future<bool> flush();
/// Get the cache key prefix.
///
/// Example:
/// ```dart
/// var prefix = store.getPrefix();
/// ```
String getPrefix();
}

View file

@ -0,0 +1,64 @@
/// Interface for configuration repository.
///
/// This contract defines the standard way to interact with configuration values
/// in the application. It provides methods to get, set, and manipulate
/// configuration values in a consistent manner.
abstract class Repository {
/// Determine if the given configuration value exists.
///
/// Example:
/// ```dart
/// if (config.has('database.default')) {
/// // Use the database configuration
/// }
/// ```
bool has(String key);
/// Get the specified configuration value.
///
/// Returns [defaultValue] if the key doesn't exist.
///
/// Example:
/// ```dart
/// var dbHost = config.get('database.connections.mysql.host', 'localhost');
/// ```
T? get<T>(String key, [T? defaultValue]);
/// Get all of the configuration items.
///
/// Example:
/// ```dart
/// var allConfig = config.all();
/// print('Database host: ${allConfig['database']['connections']['mysql']['host']}');
/// ```
Map<String, dynamic> all();
/// Set a given configuration value.
///
/// Example:
/// ```dart
/// config.set('app.timezone', 'UTC');
/// config.set('services.aws', {
/// 'key': 'your-key',
/// 'secret': 'your-secret',
/// 'region': 'us-east-1',
/// });
/// ```
void set(String key, dynamic value);
/// Prepend a value onto an array configuration value.
///
/// Example:
/// ```dart
/// config.prepend('app.providers', MyServiceProvider);
/// ```
void prepend(String key, dynamic value);
/// Push a value onto an array configuration value.
///
/// Example:
/// ```dart
/// config.push('app.providers', MyServiceProvider);
/// ```
void push(String key, dynamic value);
}

View file

@ -0,0 +1,22 @@
/// Interface for console application.
///
/// This contract defines how console commands should be executed and
/// their output managed at the application level.
abstract class ConsoleApplication {
/// Run an Artisan console command by name.
///
/// Example:
/// ```dart
/// var status = await app.call('migrate', ['--force']);
/// ```
Future<int> call(String command,
[List<String> parameters = const [], dynamic outputBuffer]);
/// Get the output from the last command.
///
/// Example:
/// ```dart
/// var lastOutput = app.output();
/// ```
String output();
}

View file

@ -0,0 +1,16 @@
/// Interface for console commands that can be run in isolation.
///
/// This contract serves as a marker interface for console commands that can
/// be run in isolation. While it doesn't define any methods, implementing
/// this interface signals that the command can be safely executed in an
/// isolated environment.
///
/// Example:
/// ```dart
/// class ImportDataCommand implements Isolatable {
/// Future<void> handle() async {
/// // Command can be run in isolation
/// }
/// }
/// ```
abstract class Isolatable {}

View file

@ -0,0 +1,63 @@
/// Interface for console command kernel.
///
/// This contract defines how console commands should be handled and managed.
/// It provides methods for bootstrapping, handling commands, and managing
/// command output.
abstract class ConsoleKernel {
/// Bootstrap the application for artisan commands.
///
/// Example:
/// ```dart
/// await kernel.bootstrap();
/// ```
Future<void> bootstrap();
/// Handle an incoming console command.
///
/// Example:
/// ```dart
/// var status = await kernel.handle(input, output);
/// ```
Future<int> handle(dynamic input, [dynamic output]);
/// Run an Artisan console command by name.
///
/// Example:
/// ```dart
/// var status = await kernel.call('migrate', ['--force']);
/// ```
Future<int> call(String command,
[List<String> parameters = const [], dynamic outputBuffer]);
/// Queue an Artisan console command by name.
///
/// Example:
/// ```dart
/// var dispatch = await kernel.queue('email:send', ['user@example.com']);
/// ```
Future<dynamic> queue(String command, [List<String> parameters = const []]);
/// Get all of the commands registered with the console.
///
/// Example:
/// ```dart
/// var commands = kernel.all();
/// ```
Map<String, dynamic> all();
/// Get the output for the last run command.
///
/// Example:
/// ```dart
/// var lastOutput = kernel.output();
/// ```
String output();
/// Terminate the application.
///
/// Example:
/// ```dart
/// await kernel.terminate(input, 0);
/// ```
Future<void> terminate(dynamic input, int status);
}

View file

@ -0,0 +1,16 @@
/// Interface for commands that prompt for missing input.
///
/// This contract serves as a marker interface for console commands that should
/// prompt for missing input arguments or options. While it doesn't define any
/// methods, implementing this interface signals that the command should
/// interactively prompt the user when required input is missing.
///
/// Example:
/// ```dart
/// class CreateUserCommand implements PromptsForMissingInput {
/// Future<void> handle() async {
/// // Command will prompt for missing input
/// }
/// }
/// ```
abstract class PromptsForMissingInput {}

View file

@ -0,0 +1,30 @@
/// Exception thrown when the container fails to resolve a binding.
class BindingResolutionException implements Exception {
/// The message describing the binding resolution failure.
final String message;
/// The original error that caused the binding resolution failure, if any.
final Object? originalError;
/// The stack trace associated with the original error, if any.
final StackTrace? stackTrace;
/// Creates a new [BindingResolutionException].
///
/// The [message] parameter describes what went wrong during binding resolution.
/// Optionally, you can provide the [originalError] and its [stackTrace] for
/// more detailed debugging information.
const BindingResolutionException(
this.message, {
this.originalError,
this.stackTrace,
});
@override
String toString() {
if (originalError != null) {
return 'BindingResolutionException: $message\nCaused by: $originalError';
}
return 'BindingResolutionException: $message';
}
}

View file

@ -0,0 +1,43 @@
/// Exception thrown when a circular dependency is detected in the container.
///
/// This exception is thrown when the container detects a circular dependency
/// while trying to resolve a type. A circular dependency occurs when type A
/// depends on type B which depends on type A, either directly or through
/// a chain of other dependencies.
///
/// Example:
/// ```dart
/// class A {
/// A(B b);
/// }
///
/// class B {
/// B(A a); // Circular dependency: A -> B -> A
/// }
///
/// try {
/// container.make('A');
/// } on CircularDependencyException catch (e) {
/// print(e.message); // "Circular dependency detected while resolving [A -> B -> A]"
/// print(e.path); // ["A", "B", "A"]
/// }
/// ```
class CircularDependencyException implements Exception {
/// The error message describing the circular dependency.
final String message;
/// The path of dependencies that form the circle.
final List<String> path;
/// Creates a new [CircularDependencyException].
///
/// The [path] parameter should contain the list of types in the order they
/// were encountered while resolving dependencies, with the last type being
/// the one that completes the circle.
CircularDependencyException(this.path)
: message =
'Circular dependency detected while resolving [${path.join(" -> ")}]';
@override
String toString() => message;
}

View file

@ -1,3 +1,107 @@
/// Container package contracts
export 'container_contract.dart';
export 'contextual_binding_contract.dart';
import 'binding_resolution_exception.dart';
import 'container_interface.dart';
import 'contextual_binding_builder.dart';
/// Interface for the IoC container.
///
/// This contract defines the interface for the Inversion of Control container,
/// which provides dependency injection and service location capabilities.
/// It extends the basic [ContainerInterface] with additional functionality
/// for binding, resolving, and managing services.
abstract class Container implements ContainerInterface {
/// Determine if the given abstract type has been bound.
bool bound(String abstract);
/// Alias a type to a different name.
///
/// Throws [ArgumentError] if the alias would cause a circular reference.
void alias(String abstract, String alias);
/// Assign a set of tags to a given binding.
void tag(dynamic abstracts, List<String> tags);
/// Resolve all of the bindings for a given tag.
Iterable<dynamic> tagged(String tag);
/// Register a binding with the container.
///
/// The [concrete] parameter can be a Type, a factory function, or null.
/// If [shared] is true, the same instance will be returned for subsequent
/// resolutions of this binding.
void bind(String abstract, dynamic concrete, {bool shared = false});
/// Bind a callback to resolve with [call].
void bindMethod(dynamic method, Function callback);
/// Register a binding if it hasn't already been registered.
void bindIf(String abstract, dynamic concrete, {bool shared = false});
/// Register a shared binding in the container.
void singleton(String abstract, [dynamic concrete]);
/// Register a shared binding if it hasn't already been registered.
void singletonIf(String abstract, [dynamic concrete]);
/// Register a scoped binding in the container.
void scoped(String abstract, [dynamic concrete]);
/// Register a scoped binding if it hasn't already been registered.
void scopedIf(String abstract, [dynamic concrete]);
/// "Extend" an abstract type in the container.
///
/// Throws [ArgumentError] if the abstract type isn't registered.
void extend(String abstract, Function(dynamic service) closure);
/// Register an existing instance as shared in the container.
T instance<T>(String abstract, T instance);
/// Add a contextual binding to the container.
void addContextualBinding(
String concrete,
String abstract,
dynamic implementation,
);
/// Define a contextual binding.
ContextualBindingBuilder when(dynamic concrete);
/// Get a factory function to resolve the given type from the container.
Function factory(String abstract);
/// Flush the container of all bindings and resolved instances.
void flush();
/// Resolve the given type from the container.
///
/// Throws [BindingResolutionException] if the type cannot be resolved.
T make<T>(String abstract, {Map<String, dynamic>? parameters});
/// Call the given callback / class@method and inject its dependencies.
dynamic call(
dynamic callback, {
Map<String, dynamic>? parameters,
String? defaultMethod,
});
/// Determine if the given abstract type has been resolved.
bool resolved(String abstract);
/// Register a new before resolving callback.
void beforeResolving(
dynamic abstract, [
void Function(Container container, String abstract)? callback,
]);
/// Register a new resolving callback.
void resolving(
dynamic abstract, [
void Function(dynamic instance, Container container)? callback,
]);
/// Register a new after resolving callback.
void afterResolving(
dynamic abstract, [
void Function(dynamic instance, Container container)? callback,
]);
}

View file

@ -0,0 +1,27 @@
/// Interface for service containers.
///
/// This contract defines the basic interface that any service container
/// must implement. It follows the PSR-11 ContainerInterface specification
/// from PHP-FIG, adapted for Dart.
abstract class ContainerInterface {
/// Finds an entry of the container by its identifier and returns it.
///
/// Example:
/// ```dart
/// var logger = container.get('logger');
/// ```
///
/// Throws [BindingResolutionException] if the identifier is not found.
dynamic get(String id);
/// Returns true if the container can return an entry for the given identifier.
/// Returns false otherwise.
///
/// Example:
/// ```dart
/// if (container.has('logger')) {
/// // Use the logger service
/// }
/// ```
bool has(String id);
}

View file

@ -0,0 +1,25 @@
/// Interface for building contextual bindings in the container.
///
/// This contract allows for fluent configuration of contextual bindings,
/// which are used to specify different concrete implementations for a
/// dependency based on the context in which it is being resolved.
abstract class ContextualBindingBuilder {
/// Define the abstract target that is being contextualized.
///
/// This method specifies which abstract type or interface should be
/// bound differently in the given context.
///
/// Example:
/// ```dart
/// container.when([UserController]).needs(Logger).give(FileLogger);
/// ```
ContextualBindingBuilder needs(dynamic abstract);
/// Define the concrete implementation that should be used.
///
/// This method specifies the concrete implementation that should be
/// used when resolving the abstract type in the given context.
///
/// The implementation can be either a concrete type or a factory function.
void give(dynamic implementation);
}

View file

@ -0,0 +1,67 @@
/// Interface for cookie factory.
///
/// This contract defines the standard way to create cookie instances
/// in the application. It provides methods to create and expire cookies
/// with various attributes.
abstract class CookieFactory {
/// Create a new cookie instance.
///
/// Example:
/// ```dart
/// var cookie = cookies.make(
/// 'preferences',
/// 'theme=dark',
/// minutes: 60,
/// secure: true,
/// sameSite: 'Lax'
/// );
/// ```
dynamic make(
String name,
String value, {
int minutes = 0,
String? path,
String? domain,
bool? secure,
bool httpOnly = true,
bool raw = false,
String? sameSite,
});
/// Create a cookie that lasts "forever" (five years).
///
/// Example:
/// ```dart
/// var cookie = cookies.forever(
/// 'user_id',
/// '12345',
/// secure: true,
/// sameSite: 'Strict'
/// );
/// ```
dynamic forever(
String name,
String value, {
String? path,
String? domain,
bool? secure,
bool httpOnly = true,
bool raw = false,
String? sameSite,
});
/// Expire the given cookie.
///
/// Creates a new cookie instance that will expire the cookie
/// when sent to the browser.
///
/// Example:
/// ```dart
/// var cookie = cookies.forget('session_id');
/// ```
dynamic forget(
String name, {
String? path,
String? domain,
});
}

View file

@ -0,0 +1,14 @@
import 'cookie_factory.dart';
/// Interface for queueing cookie factory.
abstract class QueueingFactory extends CookieFactory {
/// Queue a cookie to send with the next response.
void queue(String name, String value,
[Map<String, dynamic> options = const {}]);
/// Remove a cookie from the queue.
void unqueue(String name);
/// Get the queued cookies.
Map<String, dynamic> getQueuedCookies();
}

View file

@ -0,0 +1,8 @@
import '../query/builder.dart';
/// Interface for Eloquent query builder.
///
/// This contract serves as a marker interface for Eloquent query builders.
/// While it doesn't define any methods, it exists to improve IDE support
/// and type safety when working with Eloquent query builders.
abstract class EloquentBuilder extends QueryBuilder {}

View file

@ -0,0 +1,40 @@
import 'casts_attributes.dart';
import 'casts_inbound_attributes.dart';
/// Interface for classes that can specify their own casting behavior.
///
/// This contract defines how a class can specify which caster should be used
/// when casting its values to and from the database.
abstract class Castable {
/// Get the name of the caster class to use when casting from / to this cast target.
///
/// Example:
/// ```dart
/// class Location implements Castable {
/// final double lat;
/// final double lng;
///
/// Location(this.lat, this.lng);
///
/// @override
/// dynamic castUsing(List<dynamic> arguments) {
/// return LocationCaster();
/// }
/// }
///
/// class LocationCaster implements CastsAttributes<Location, Map<String, dynamic>> {
/// @override
/// Location? get(dynamic model, String key, dynamic value, Map<String, dynamic> attributes) {
/// if (value == null) return null;
/// return Location(value['lat'], value['lng']);
/// }
///
/// @override
/// dynamic set(dynamic model, String key, Location? value, Map<String, dynamic> attributes) {
/// if (value == null) return null;
/// return {'lat': value.lat, 'lng': value.lng};
/// }
/// }
/// ```
dynamic castUsing(List<dynamic> arguments);
}

View file

@ -0,0 +1,52 @@
/// Interface for custom attribute casting.
///
/// This contract defines how model attributes should be cast to and from
/// their database representation. It provides methods for transforming
/// attributes when they are retrieved from or set on a model.
abstract class CastsAttributes<TGet, TSet> {
/// Transform the attribute from the underlying model values.
///
/// Example:
/// ```dart
/// class JsonCast implements CastsAttributes<Map<String, dynamic>, String> {
/// @override
/// Map<String, dynamic>? get(
/// Model model,
/// String key,
/// dynamic value,
/// Map<String, dynamic> attributes,
/// ) {
/// return value != null ? jsonDecode(value) : null;
/// }
/// }
/// ```
TGet? get(
dynamic model,
String key,
dynamic value,
Map<String, dynamic> attributes,
);
/// Transform the attribute to its underlying model values.
///
/// Example:
/// ```dart
/// class JsonCast implements CastsAttributes<Map<String, dynamic>, String> {
/// @override
/// dynamic set(
/// Model model,
/// String key,
/// String? value,
/// Map<String, dynamic> attributes,
/// ) {
/// return value != null ? jsonEncode(value) : null;
/// }
/// }
/// ```
dynamic set(
dynamic model,
String key,
TSet? value,
Map<String, dynamic> attributes,
);
}

View file

@ -0,0 +1,29 @@
/// Interface for inbound attribute casting.
///
/// This contract defines how model attributes should be cast when they are
/// set on a model. Unlike [CastsAttributes], this interface only handles
/// the transformation of values being set, not retrieved.
abstract class CastsInboundAttributes {
/// Transform the attribute to its underlying model values.
///
/// Example:
/// ```dart
/// class PasswordCast implements CastsInboundAttributes {
/// @override
/// dynamic set(
/// dynamic model,
/// String key,
/// dynamic value,
/// Map<String, dynamic> attributes,
/// ) {
/// return value != null ? hashPassword(value) : null;
/// }
/// }
/// ```
dynamic set(
dynamic model,
String key,
dynamic value,
Map<String, dynamic> attributes,
);
}

View file

@ -0,0 +1,56 @@
/// Interface for incrementing and decrementing castable attributes.
///
/// This contract defines how model attributes should be modified when
/// performing increment and decrement operations. It allows custom casts
/// to handle these operations in a way that makes sense for their data type.
abstract class DeviatesCastableAttributes {
/// Increment the attribute.
///
/// Example:
/// ```dart
/// class JsonCounterCast implements DeviatesCastableAttributes {
/// @override
/// dynamic increment(
/// dynamic model,
/// String key,
/// dynamic value,
/// Map<String, dynamic> attributes,
/// ) {
/// var data = jsonDecode(attributes[key] ?? '{"count": 0}');
/// data['count'] += value;
/// return jsonEncode(data);
/// }
/// }
/// ```
dynamic increment(
dynamic model,
String key,
dynamic value,
Map<String, dynamic> attributes,
);
/// Decrement the attribute.
///
/// Example:
/// ```dart
/// class JsonCounterCast implements DeviatesCastableAttributes {
/// @override
/// dynamic decrement(
/// dynamic model,
/// String key,
/// dynamic value,
/// Map<String, dynamic> attributes,
/// ) {
/// var data = jsonDecode(attributes[key] ?? '{"count": 0}');
/// data['count'] -= value;
/// return jsonEncode(data);
/// }
/// }
/// ```
dynamic decrement(
dynamic model,
String key,
dynamic value,
Map<String, dynamic> attributes,
);
}

View file

@ -0,0 +1,29 @@
/// Interface for serializing castable attributes.
///
/// This contract defines how model attributes should be serialized when
/// converting a model to an array or JSON. It allows custom casts to
/// control how their values are represented in array/JSON form.
abstract class SerializesCastableAttributes {
/// Serialize the attribute when converting the model to an array.
///
/// Example:
/// ```dart
/// class DateCast implements SerializesCastableAttributes {
/// @override
/// dynamic serialize(
/// dynamic model,
/// String key,
/// dynamic value,
/// Map<String, dynamic> attributes,
/// ) {
/// return value?.toIso8601String();
/// }
/// }
/// ```
dynamic serialize(
dynamic model,
String key,
dynamic value,
Map<String, dynamic> attributes,
);
}

View file

@ -0,0 +1,40 @@
/// Interface for models that support partial relations.
///
/// This contract defines how models should handle one-of-many relationships,
/// which are used to retrieve a single record from a one-to-many relationship
/// based on some aggregate condition.
abstract class SupportsPartialRelations {
/// Indicate that the relation is a single result of a larger one-to-many relationship.
///
/// Example:
/// ```dart
/// // Get the user's latest post
/// user.ofMany('created_at', 'MAX', 'posts');
///
/// // Get the user's most expensive order
/// user.ofMany('total', 'MAX', 'orders');
/// ```
dynamic ofMany([
String column = 'id',
String aggregate = 'MAX',
String? relation,
]);
/// Determine whether the relationship is a one-of-many relationship.
///
/// Example:
/// ```dart
/// if (user.latestPost.isOneOfMany()) {
/// // Handle one-of-many relationship
/// }
/// ```
bool isOneOfMany();
/// Get the one of many inner join subselect query builder instance.
///
/// Example:
/// ```dart
/// var subQuery = user.latestPost.getOneOfManySubQuery();
/// ```
dynamic getOneOfManySubQuery();
}

View file

@ -0,0 +1,4 @@
/// Interface for migration events.
///
/// This contract serves as a marker interface for migration events.
abstract class MigrationEvent {}

View file

@ -0,0 +1,35 @@
/// Class for model serialization.
///
/// This class is used to identify models during serialization.
class ModelIdentifier {
/// The class name of the model.
final String className;
/// The unique identifier of the model.
///
/// This may be either a single ID or an array of IDs.
final dynamic id;
/// The relationships loaded on the model.
final List<String> relations;
/// The connection name of the model.
final String? connection;
/// The class name of the model collection.
String? collectionClass;
/// Create a new model identifier.
ModelIdentifier(
this.className,
this.id,
this.relations,
this.connection,
);
/// Specify the collection class that should be used when serializing / restoring collections.
ModelIdentifier useCollectionClass(String? collectionClass) {
this.collectionClass = collectionClass;
return this;
}
}

View file

@ -0,0 +1,6 @@
/// Interface for database query builder.
///
/// This contract serves as a marker interface for query builders.
/// While it doesn't define any methods, it exists to improve IDE support
/// and type safety when working with query builders.
abstract class QueryBuilder {}

View file

@ -0,0 +1,6 @@
import 'expression.dart';
/// Interface for database query condition expressions.
///
/// This contract serves as a marker interface for condition expressions.
abstract class ConditionExpression extends Expression {}

View file

@ -0,0 +1,7 @@
/// Interface for database query expressions.
///
/// This contract defines how raw SQL expressions should be handled.
abstract class Expression {
/// Get the value of the expression.
dynamic getValue(dynamic grammar);
}

View file

@ -0,0 +1,25 @@
import 'dart:async';
import 'package:meta/meta.dart';
/// Interface for handling exceptions.
abstract class ExceptionHandler {
/// Report or log an exception.
///
/// @throws Exception
FutureOr<void> report(Object error, [StackTrace? stackTrace]);
/// Determine if the exception should be reported.
bool shouldReport(Object error);
/// Render an exception into an HTTP response.
///
/// @throws Exception
FutureOr<dynamic> render(dynamic request, Object error,
[StackTrace? stackTrace]);
/// Render an exception to the console.
///
/// This method is not meant to be used or overwritten outside the framework.
@protected
void renderForConsole(dynamic output, Object error, [StackTrace? stackTrace]);
}

View file

@ -0,0 +1,2 @@
/// Exception thrown during decryption.
class DecryptException implements Exception {}

View file

@ -0,0 +1,2 @@
/// Exception thrown during encryption.
class EncryptException implements Exception {}

View file

@ -0,0 +1,21 @@
/// Interface for encryption.
abstract class Encrypter {
/// Encrypt the given value.
///
/// @throws EncryptException
String encrypt(dynamic value, [bool serialize = true]);
/// Decrypt the given value.
///
/// @throws DecryptException
dynamic decrypt(String payload, [bool unserialize = true]);
/// Get the encryption key that the encrypter is currently using.
String getKey();
/// Get the current encryption key and all previous encryption keys.
List<String> getAllKeys();
/// Get the previous encryption keys.
List<String> getPreviousKeys();
}

View file

@ -0,0 +1,12 @@
/// Interface for string encryption.
abstract class StringEncrypter {
/// Encrypt a string without serialization.
///
/// @throws EncryptException
String encryptString(String value);
/// Decrypt the given string without unserialization.
///
/// @throws DecryptException
String decryptString(String payload);
}

View file

@ -0,0 +1,30 @@
/// Interface for event dispatching.
abstract class Dispatcher {
/// Register an event listener with the dispatcher.
void listen(dynamic events, [dynamic listener]);
/// Determine if a given event has listeners.
bool hasListeners(String eventName);
/// Register an event subscriber with the dispatcher.
void subscribe(dynamic subscriber);
/// Dispatch an event until the first non-null response is returned.
dynamic until(dynamic event, [dynamic payload = const []]);
/// Dispatch an event and call the listeners.
List<dynamic>? dispatch(dynamic event,
[dynamic payload = const [], bool halt = false]);
/// Register an event and payload to be fired later.
void push(String event, [List<dynamic> payload = const []]);
/// Flush a set of pushed events.
void flush(String event);
/// Remove a set of listeners from the dispatcher.
void forget(String event);
/// Forget all of the queued listeners.
void forgetPushed();
}

View file

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

View file

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

View file

@ -0,0 +1,5 @@
/// Interface for events that should be dispatched after database commit.
///
/// This contract serves as a marker interface for events that should
/// only be dispatched after their database transaction has been committed.
abstract class ShouldDispatchAfterCommit {}

View file

@ -0,0 +1,5 @@
/// Interface for events that should be handled after database commit.
///
/// This contract serves as a marker interface for events that should
/// only be handled after their database transaction has been committed.
abstract class ShouldHandleEventsAfterCommit {}

View file

@ -0,0 +1,7 @@
import 'filesystem.dart';
/// Interface for cloud filesystem operations.
abstract class Cloud extends Filesystem {
/// Get the URL for the file at the given path.
String url(String path);
}

View file

@ -0,0 +1,2 @@
/// Exception thrown when a file is not found.
class FileNotFoundException implements Exception {}

View file

@ -0,0 +1,83 @@
import 'dart:async';
/// Interface for filesystem operations.
abstract class Filesystem {
/// The public visibility setting.
static const String visibilityPublic = 'public';
/// The private visibility setting.
static const String visibilityPrivate = 'private';
/// Get the full path to the file at the given relative path.
String path(String path);
/// Determine if a file exists.
Future<bool> exists(String path);
/// Get the contents of a file.
Future<String?> get(String path);
/// Get a resource to read the file.
Future<Stream<List<int>>?> readStream(String path);
/// Write the contents of a file.
Future<bool> put(String path, dynamic contents,
[Map<String, dynamic> options = const {}]);
/// Store the uploaded file on the disk.
Future<String?> putFile(String path,
[dynamic file, Map<String, dynamic> options = const {}]);
/// Store the uploaded file on the disk with a given name.
Future<String?> putFileAs(String path, dynamic file,
[String? name, Map<String, dynamic> options = const {}]);
/// Write a new file using a stream.
Future<bool> writeStream(String path, Stream<List<int>> resource,
[Map<String, dynamic> options = const {}]);
/// Get the visibility for the given path.
Future<String> getVisibility(String path);
/// Set the visibility for the given path.
Future<bool> setVisibility(String path, String visibility);
/// Prepend to a file.
Future<bool> prepend(String path, String data);
/// Append to a file.
Future<bool> append(String path, String data);
/// Delete the file at a given path.
Future<bool> delete(dynamic paths);
/// Copy a file to a new location.
Future<bool> copy(String from, String to);
/// Move a file to a new location.
Future<bool> move(String from, String to);
/// Get the file size of a given file.
Future<int> size(String path);
/// Get the file's last modification time.
Future<int> lastModified(String path);
/// Get an array of all files in a directory.
Future<List<String>> files([String? directory, bool recursive = false]);
/// Get all of the files from the given directory (recursive).
Future<List<String>> allFiles([String? directory]);
/// Get all of the directories within a given directory.
Future<List<String>> directories([String? directory, bool recursive = false]);
/// Get all (recursive) of the directories within a given directory.
Future<List<String>> allDirectories([String? directory]);
/// Create a directory.
Future<bool> makeDirectory(String path);
/// Recursively delete a directory.
Future<bool> deleteDirectory(String directory);
}

View file

@ -0,0 +1,7 @@
import 'filesystem.dart';
/// Interface for filesystem factory.
abstract class FilesystemFactory {
/// Get a filesystem implementation.
Filesystem disk([String? name]);
}

View file

@ -0,0 +1,2 @@
/// Exception thrown when a filesystem lock operation times out.
class LockTimeoutException implements Exception {}

View file

@ -0,0 +1,100 @@
import '../container/container.dart';
/// Interface for the application.
abstract class Application extends Container {
/// Get the version number of the application.
String version();
/// Get the base path of the installation.
String basePath([String path = '']);
/// Get the path to the bootstrap directory.
String bootstrapPath([String path = '']);
/// Get the path to the application configuration files.
String configPath([String path = '']);
/// Get the path to the database directory.
String databasePath([String path = '']);
/// Get the path to the language files.
String langPath([String path = '']);
/// Get the path to the public directory.
String publicPath([String path = '']);
/// Get the path to the resources directory.
String resourcePath([String path = '']);
/// Get the path to the storage directory.
String storagePath([String path = '']);
/// Get or check the current application environment.
dynamic environment(List<String> environments);
/// Determine if the application is running in the console.
bool runningInConsole();
/// Determine if the application is running unit tests.
bool runningUnitTests();
/// Determine if the application is running with debug mode enabled.
bool hasDebugModeEnabled();
/// Get an instance of the maintenance mode manager implementation.
dynamic maintenanceMode();
/// Determine if the application is currently down for maintenance.
bool isDownForMaintenance();
/// Register all of the configured providers.
void registerConfiguredProviders();
/// Register a service provider with the application.
dynamic register(dynamic provider, [bool force = false]);
/// Register a deferred provider and service.
void registerDeferredProvider(String provider, [String? service]);
/// Resolve a service provider instance from the class name.
dynamic resolveProvider(String provider);
/// Boot the application's service providers.
void boot();
/// Register a new boot listener.
void booting(Function callback);
/// Register a new "booted" listener.
void booted(Function callback);
/// Run the given array of bootstrap classes.
void bootstrapWith(List<dynamic> bootstrappers);
/// Get the current application locale.
String getLocale();
/// Get the application namespace.
String getNamespace();
/// Get the registered service provider instances if any exist.
List<dynamic> getProviders(dynamic provider);
/// Determine if the application has been bootstrapped before.
bool hasBeenBootstrapped();
/// Load and boot all of the remaining deferred providers.
void loadDeferredProviders();
/// Set the current application locale.
void setLocale(String locale);
/// Determine if middleware has been disabled for the application.
bool shouldSkipMiddleware();
/// Register a terminating callback with the application.
Application terminating(dynamic callback);
/// Terminate the application.
void terminate();
}

View file

@ -0,0 +1,11 @@
/// Interface for configuration caching.
abstract class CachesConfiguration {
/// Determine if the application configuration is cached.
bool configurationIsCached();
/// Get the path to the configuration cache file.
String getCachedConfigPath();
/// Get the path to the cached services.php file.
String getCachedServicesPath();
}

View file

@ -0,0 +1,8 @@
/// Interface for route caching.
abstract class CachesRoutes {
/// Determine if the application routes are cached.
bool routesAreCached();
/// Get the path to the routes cache file.
String getCachedRoutesPath();
}

View file

@ -0,0 +1,5 @@
/// Interface for rendering exceptions as HTML.
abstract class ExceptionRenderer {
/// Renders the given exception as HTML.
String render(Object throwable);
}

View file

@ -0,0 +1,14 @@
/// Interface for maintenance mode management.
abstract class MaintenanceMode {
/// Take the application down for maintenance.
void activate(Map<String, dynamic> payload);
/// Take the application out of maintenance.
void deactivate();
/// Determine if the application is currently down for maintenance.
bool active();
/// Get the data array which was provided when the application was placed into maintenance.
Map<String, dynamic> data();
}

View file

@ -0,0 +1,16 @@
/// Interface for hashing.
abstract class Hasher {
/// Get information about the given hashed value.
Map<String, dynamic> info(String hashedValue);
/// Hash the given value.
String make(String value, [Map<String, dynamic> options = const {}]);
/// Check the given plain value against a hash.
bool check(String value, String hashedValue,
[Map<String, dynamic> options = const {}]);
/// Check if the given hash has been hashed using the given options.
bool needsRehash(String hashedValue,
[Map<String, dynamic> options = const {}]);
}

View file

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

View file

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

View file

@ -0,0 +1,16 @@
import '../foundation/application.dart';
/// Interface for HTTP kernel.
abstract class Kernel {
/// Bootstrap the application for HTTP requests.
void bootstrap();
/// Handle an incoming HTTP request.
dynamic handle(dynamic request);
/// Perform any final actions for the request lifecycle.
void terminate(dynamic request, dynamic response);
/// Get the application instance.
Application getApplication();
}

View file

@ -0,0 +1,32 @@
/// Abstract representation of an HTTP request.
///
/// This class serves as a base contract for HTTP requests across the framework.
/// Concrete implementations will provide the actual request handling logic.
abstract class Request {
/// Get the request method.
String get method;
/// Get the request URI.
Uri get uri;
/// Get all request headers.
Map<String, List<String>> get headers;
/// Get the request body.
dynamic get body;
/// Get a request header value.
String? header(String name);
/// Get a query parameter value.
String? query(String name);
/// Get all query parameters.
Map<String, String> get queryParameters;
/// Determine if the request is AJAX.
bool get isAjax;
/// Determine if the request expects JSON.
bool get expectsJson;
}

View file

@ -0,0 +1,48 @@
/// Abstract representation of an HTTP response.
///
/// This class serves as a base contract for HTTP responses across the framework.
/// Concrete implementations will provide the actual response handling logic.
abstract class Response {
/// Get the response status code.
int get statusCode;
/// Set the response status code.
set statusCode(int value);
/// Get all response headers.
Map<String, List<String>> get headers;
/// Get the response body.
dynamic get body;
/// Set the response body.
set body(dynamic value);
/// Set a response header.
void header(String name, String value);
/// Remove a response header.
void removeHeader(String name);
/// Set the content type header.
void contentType(String value);
/// Get a response header value.
String? getHeader(String name);
/// Determine if the response has a given header.
bool hasHeader(String name);
/// Set the response content.
void setContent(dynamic content);
/// Get the response content.
dynamic getContent();
/// Convert the response to bytes.
List<int> toBytes();
/// Convert the response to a string.
@override
String toString();
}

View file

@ -0,0 +1,5 @@
/// Interface for mail attachments.
abstract class Attachable {
/// Get an attachment instance for this entity.
dynamic toMailAttachment();
}

View file

@ -0,0 +1,7 @@
import 'mailer.dart';
/// Interface for mail factory.
abstract class MailFactory {
/// Get a mailer instance by name.
Mailer mailer([String? name]);
}

View file

@ -0,0 +1,8 @@
/// Interface for queued mail sending.
abstract class MailQueue {
/// Queue a new e-mail message for sending.
dynamic queue(dynamic view, [String? queue]);
/// Queue a new e-mail message for sending after (n) seconds.
dynamic later(dynamic delay, dynamic view, [String? queue]);
}

View file

@ -0,0 +1,26 @@
/// Interface for mail messages.
abstract class Mailable {
/// Send the message using the given mailer.
dynamic send(dynamic mailer);
/// Queue the given message.
dynamic queue(dynamic queue);
/// Deliver the queued message after (n) seconds.
dynamic later(dynamic delay, dynamic queue);
/// Set the CC recipients of the message.
Mailable cc(dynamic address, [String? name]);
/// Set the BCC recipients of the message.
Mailable bcc(dynamic address, [String? name]);
/// Set the recipients of the message.
Mailable to(dynamic address, [String? name]);
/// Set the locale of the message.
Mailable locale(String locale);
/// Set the name of the mailer that should be used to send the message.
Mailable mailer(String mailer);
}

View file

@ -0,0 +1,19 @@
/// Interface for mail sending.
abstract class Mailer {
/// Begin the process of mailing a mailable class instance.
dynamic to(dynamic users);
/// Begin the process of mailing a mailable class instance.
dynamic bcc(dynamic users);
/// Send a new message with only a raw text part.
dynamic raw(String text, dynamic callback);
/// Send a new message using a view.
dynamic send(dynamic view,
[Map<String, dynamic> data = const {}, dynamic callback]);
/// Send a new message synchronously using a view.
dynamic sendNow(dynamic mailable,
[Map<String, dynamic> data = const {}, dynamic callback]);
}

View file

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

View file

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

View file

@ -0,0 +1,9 @@
/// Interface for notification dispatching.
abstract class Dispatcher {
/// Send the given notification to the given notifiable entities.
void send(dynamic notifiables, dynamic notification);
/// Send the given notification immediately.
void sendNow(dynamic notifiables, dynamic notification,
[List<String>? channels]);
}

View file

@ -0,0 +1,11 @@
/// Interface for notification factory.
abstract class Factory {
/// Get a channel instance by name.
dynamic channel([String? name]);
/// Send the given notification to the given notifiable entities.
void send(dynamic notifiables, dynamic notification);
/// Send the given notification immediately.
void sendNow(dynamic notifiables, dynamic notification);
}

View file

@ -0,0 +1,50 @@
/// Interface for cursor-based pagination.
abstract class CursorPaginator {
/// Get the URL for a given cursor.
String url(dynamic cursor);
/// Add a set of query string values to the paginator.
CursorPaginator appends(dynamic key, [String? value]);
/// Get / set the URL fragment to be appended to URLs.
dynamic fragment([String? fragment]);
/// Add all current query string values to the paginator.
CursorPaginator withQueryString();
/// Get the URL for the previous page, or null.
String? previousPageUrl();
/// The URL for the next page, or null.
String? nextPageUrl();
/// Get all of the items being paginated.
List<dynamic> items();
/// Get the "cursor" of the previous set of items.
dynamic previousCursor();
/// Get the "cursor" of the next set of items.
dynamic nextCursor();
/// Determine how many items are being shown per page.
int perPage();
/// Get the current cursor being paginated.
dynamic cursor();
/// Determine if there are enough items to split into multiple pages.
bool hasPages();
/// Get the base path for paginator generated URLs.
String? path();
/// Determine if the list of items is empty or not.
bool isEmpty();
/// Determine if the list of items is not empty.
bool isNotEmpty();
/// Render the paginator using a given view.
String render([String? view, Map<String, dynamic> data = const {}]);
}

View file

@ -0,0 +1,13 @@
import 'paginator.dart';
/// Interface for pagination with total count awareness.
abstract class LengthAwarePaginator extends Paginator {
/// Create a range of pagination URLs.
List<String> getUrlRange(int start, int end);
/// Determine the total number of items in the data store.
int total();
/// Get the page number of the last available page.
int lastPage();
}

View file

@ -0,0 +1,50 @@
/// Interface for pagination.
abstract class Paginator {
/// Get the URL for a given page.
String url(int page);
/// Add a set of query string values to the paginator.
Paginator appends(dynamic key, [String? value]);
/// Get / set the URL fragment to be appended to URLs.
dynamic fragment([String? fragment]);
/// The URL for the next page, or null.
String? nextPageUrl();
/// Get the URL for the previous page, or null.
String? previousPageUrl();
/// Get all of the items being paginated.
List<dynamic> items();
/// Get the "index" of the first item being paginated.
int? firstItem();
/// Get the "index" of the last item being paginated.
int? lastItem();
/// Determine how many items are being shown per page.
int perPage();
/// Determine the current page being paginated.
int currentPage();
/// Determine if there are enough items to split into multiple pages.
bool hasPages();
/// Determine if there are more items in the data store.
bool hasMorePages();
/// Get the base path for paginator generated URLs.
String? path();
/// Determine if the list of items is empty or not.
bool isEmpty();
/// Determine if the list of items is not empty.
bool isNotEmpty();
/// Render the paginator using a given view.
String render([String? view, Map<String, dynamic> data = const {}]);
}

View file

@ -0,0 +1,5 @@
/// Interface for pipeline management.
abstract class Hub {
/// Send an object through one of the available pipelines.
dynamic pipe(dynamic object, [String? pipeline]);
}

View file

@ -1,2 +1,14 @@
/// Pipeline package contracts
export 'pipeline_contract.dart';
/// Interface for pipeline processing.
abstract class Pipeline {
/// Set the traveler object being sent on the pipeline.
Pipeline send(dynamic traveler);
/// Set the stops of the pipeline.
Pipeline through(dynamic stops);
/// Set the method to call on the stops.
Pipeline via(String method);
/// Run the pipeline with a final destination callback.
dynamic then(Function destination);
}

View file

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

View file

@ -0,0 +1,28 @@
import 'process_result.dart';
/// Interface for running processes.
abstract class InvokedProcess {
/// Get the process ID if the process is still running.
int? id();
/// Send a signal to the process.
InvokedProcess signal(int signal);
/// Determine if the process is still running.
bool running();
/// Get the standard output for the process.
String output();
/// Get the error output for the process.
String errorOutput();
/// Get the latest standard output for the process.
String latestOutput();
/// Get the latest error output for the process.
String latestErrorOutput();
/// Wait for the process to finish.
ProcessResult wait([Function? output]);
}

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