feat: Phase 2 - Laravel Reverb + real-time notifications
- Install laravel/reverb + laravel-echo + pusher-js - Configure broadcasting to reverb in .env.example + .env - Add Echo + Pusher client in resources/js/app.js - Update all 14 notifications to implement ShouldBroadcast + broadcastOn() - Update NotificationBell component to listen for real-time events - Add Livewire.emit in notification-bell blade for JS-to-Livewire bridge Tests: 101 passing (319 assertions)
This commit is contained in:
+8
-1
@@ -33,7 +33,7 @@ SESSION_ENCRYPT=false
|
||||
SESSION_PATH=/
|
||||
SESSION_DOMAIN=null
|
||||
|
||||
BROADCAST_CONNECTION=log
|
||||
BROADCAST_CONNECTION=reverb
|
||||
FILESYSTEM_DISK=local
|
||||
QUEUE_CONNECTION=redis
|
||||
|
||||
@@ -47,6 +47,13 @@ REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
REVERB_APP_ID=1
|
||||
REVERB_APP_KEY=local
|
||||
REVERB_APP_SECRET=secret
|
||||
REVERB_HOST=127.0.0.1
|
||||
REVERB_PORT=8080
|
||||
REVERB_SCHEME=http
|
||||
|
||||
MAIL_MAILER=log
|
||||
MAIL_SCHEME=null
|
||||
MAIL_HOST=127.0.0.1
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Livewire\Common;
|
||||
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Livewire\Attributes\On;
|
||||
use Livewire\Component;
|
||||
|
||||
class NotificationBell extends Component
|
||||
@@ -37,6 +38,13 @@ class NotificationBell extends Component
|
||||
$this->loadNotifications();
|
||||
}
|
||||
|
||||
#[On('notification-received')]
|
||||
public function handleNotification($message = 'Nueva notificación')
|
||||
{
|
||||
$this->loadNotifications();
|
||||
$this->dispatch('notify', $message);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.common.notification-bell');
|
||||
|
||||
@@ -4,9 +4,10 @@ namespace App\Notifications;
|
||||
|
||||
use App\Models\Feature;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class FeatureCompletedNotification extends Notification
|
||||
class FeatureCompletedNotification extends Notification implements ShouldBroadcast
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
@@ -14,7 +15,7 @@ class FeatureCompletedNotification extends Notification
|
||||
|
||||
public function via($notifiable): array
|
||||
{
|
||||
return ['database'];
|
||||
return ['database', 'broadcast'];
|
||||
}
|
||||
|
||||
public function toArray($notifiable): array
|
||||
@@ -28,4 +29,14 @@ class FeatureCompletedNotification extends Notification
|
||||
'message' => "Elemento '{$this->feature->name}' marcado como completado",
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function broadcastOn(): array
|
||||
{
|
||||
$projectId = $this->feature->layer?->phase?->project_id;
|
||||
if (! $projectId) {
|
||||
return [];
|
||||
}
|
||||
$userIds = \App\Models\Project::find($projectId)?->users->pluck('id')->toArray() ?? [];
|
||||
return array_map(fn ($id) => new \Illuminate\Broadcasting\PrivateChannel("user.{$id}"), $userIds);
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,10 @@ namespace App\Notifications;
|
||||
|
||||
use App\Models\Inspection;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class InspectionCompletedNotification extends Notification
|
||||
class InspectionCompletedNotification extends Notification implements ShouldBroadcast
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
@@ -14,7 +15,7 @@ class InspectionCompletedNotification extends Notification
|
||||
|
||||
public function via($notifiable): array
|
||||
{
|
||||
return ['database'];
|
||||
return ['database', 'broadcast'];
|
||||
}
|
||||
|
||||
public function toArray($notifiable): array
|
||||
@@ -29,4 +30,10 @@ class InspectionCompletedNotification extends Notification
|
||||
'message' => "Inspección completada en '{$this->inspection->feature?->name}': ".($this->inspection->result ?? 'sin resultado'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function broadcastOn(): array
|
||||
{
|
||||
$userIds = $this->inspection->project->users->pluck('id')->toArray();
|
||||
return array_map(fn ($id) => new \Illuminate\Broadcasting\PrivateChannel("user.{$id}"), $userIds);
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,10 @@ namespace App\Notifications;
|
||||
|
||||
use App\Models\Inspection;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class InspectionDeletedNotification extends Notification
|
||||
class InspectionDeletedNotification extends Notification implements ShouldBroadcast
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
@@ -14,7 +15,7 @@ class InspectionDeletedNotification extends Notification
|
||||
|
||||
public function via($notifiable): array
|
||||
{
|
||||
return ['database'];
|
||||
return ['database', 'broadcast'];
|
||||
}
|
||||
|
||||
public function toArray($notifiable): array
|
||||
@@ -29,4 +30,10 @@ class InspectionDeletedNotification extends Notification
|
||||
'message' => "Inspección eliminada en '{$this->inspection->feature?->name}' por {$this->deletedBy}",
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function broadcastOn(): array
|
||||
{
|
||||
$userIds = $this->inspection->project->users->pluck('id')->toArray();
|
||||
return array_map(fn ($id) => new \Illuminate\Broadcasting\PrivateChannel("user.{$id}"), $userIds);
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,10 @@ namespace App\Notifications;
|
||||
|
||||
use App\Models\Inspection;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class InspectionUpdatedNotification extends Notification
|
||||
class InspectionUpdatedNotification extends Notification implements ShouldBroadcast
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
@@ -14,7 +15,7 @@ class InspectionUpdatedNotification extends Notification
|
||||
|
||||
public function via($notifiable): array
|
||||
{
|
||||
return ['database'];
|
||||
return ['database', 'broadcast'];
|
||||
}
|
||||
|
||||
public function toArray($notifiable): array
|
||||
@@ -30,4 +31,10 @@ class InspectionUpdatedNotification extends Notification
|
||||
'message' => "Inspección actualizada en '{$this->inspection->feature?->name}'",
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function broadcastOn(): array
|
||||
{
|
||||
$userIds = $this->inspection->project->users->pluck('id')->toArray();
|
||||
return array_map(fn ($id) => new \Illuminate\Broadcasting\PrivateChannel("user.{$id}"), $userIds);
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,10 @@ namespace App\Notifications;
|
||||
|
||||
use App\Models\Issue;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class IssueAssignedNotification extends Notification
|
||||
class IssueAssignedNotification extends Notification implements ShouldBroadcast
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
@@ -14,7 +15,7 @@ class IssueAssignedNotification extends Notification
|
||||
|
||||
public function via($notifiable): array
|
||||
{
|
||||
return ['database'];
|
||||
return ['database', 'broadcast'];
|
||||
}
|
||||
|
||||
public function toArray($notifiable): array
|
||||
@@ -27,4 +28,9 @@ class IssueAssignedNotification extends Notification
|
||||
'message' => "Se te ha asignado la incidencia '{$this->issue->title}'",
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function broadcastOn(): array
|
||||
{
|
||||
return [new \Illuminate\Broadcasting\PrivateChannel('user.'.$this->issue->assigned_to)];
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,11 @@ namespace App\Notifications;
|
||||
|
||||
use App\Models\IssueComment;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class IssueCommentedNotification extends Notification
|
||||
class IssueCommentedNotification extends Notification implements ShouldBroadcast
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
@@ -15,7 +16,7 @@ class IssueCommentedNotification extends Notification
|
||||
|
||||
public function via($notifiable): array
|
||||
{
|
||||
return ['database'];
|
||||
return ['database', 'broadcast'];
|
||||
}
|
||||
|
||||
public function toArray($notifiable): array
|
||||
@@ -30,4 +31,13 @@ class IssueCommentedNotification extends Notification
|
||||
'message' => "{$this->comment->user?->name} comentó en '{$issue?->title}': ".Str::limit($this->comment->body, 60),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function broadcastOn(): array
|
||||
{
|
||||
$issue = $this->comment->issue;
|
||||
$userIds = [];
|
||||
if ($issue->assigned_to) $userIds[] = $issue->assigned_to;
|
||||
if ($issue->reported_by) $userIds[] = $issue->reported_by;
|
||||
return array_map(fn ($id) => new \Illuminate\Broadcasting\PrivateChannel("user.{$id}"), array_unique($userIds));
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,10 @@ namespace App\Notifications;
|
||||
|
||||
use App\Models\Issue;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class IssueReportedNotification extends Notification
|
||||
class IssueReportedNotification extends Notification implements ShouldBroadcast
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
@@ -14,7 +15,7 @@ class IssueReportedNotification extends Notification
|
||||
|
||||
public function via($notifiable): array
|
||||
{
|
||||
return ['database'];
|
||||
return ['database', 'broadcast'];
|
||||
}
|
||||
|
||||
public function toArray($notifiable): array
|
||||
@@ -28,4 +29,10 @@ class IssueReportedNotification extends Notification
|
||||
'message' => "Nuevo issue '{$this->issue->title}' (prioridad: {$this->issue->priority})",
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function broadcastOn(): array
|
||||
{
|
||||
$userIds = $this->issue->project->users->pluck('id')->toArray();
|
||||
return array_map(fn ($id) => new \Illuminate\Broadcasting\PrivateChannel("user.{$id}"), $userIds);
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,10 @@ namespace App\Notifications;
|
||||
|
||||
use App\Models\Issue;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class IssueStatusChangedNotification extends Notification
|
||||
class IssueStatusChangedNotification extends Notification implements ShouldBroadcast
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
@@ -14,7 +15,7 @@ class IssueStatusChangedNotification extends Notification
|
||||
|
||||
public function via($notifiable): array
|
||||
{
|
||||
return ['database'];
|
||||
return ['database', 'broadcast'];
|
||||
}
|
||||
|
||||
public function toArray($notifiable): array
|
||||
@@ -34,4 +35,12 @@ class IssueStatusChangedNotification extends Notification
|
||||
'message' => "La incidencia '{$this->issue->title}' ha sido {$label}",
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function broadcastOn(): array
|
||||
{
|
||||
$userIds = [];
|
||||
if ($this->issue->assigned_to) $userIds[] = $this->issue->assigned_to;
|
||||
if ($this->issue->reported_by) $userIds[] = $this->issue->reported_by;
|
||||
return array_map(fn ($id) => new \Illuminate\Broadcasting\PrivateChannel("user.{$id}"), array_unique($userIds));
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,10 @@ namespace App\Notifications;
|
||||
|
||||
use App\Models\IssueTask;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class IssueTaskAssignedNotification extends Notification
|
||||
class IssueTaskAssignedNotification extends Notification implements ShouldBroadcast
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
@@ -14,7 +15,7 @@ class IssueTaskAssignedNotification extends Notification
|
||||
|
||||
public function via($notifiable): array
|
||||
{
|
||||
return ['database'];
|
||||
return ['database', 'broadcast'];
|
||||
}
|
||||
|
||||
public function toArray($notifiable): array
|
||||
@@ -28,4 +29,9 @@ class IssueTaskAssignedNotification extends Notification
|
||||
'message' => "Se te ha asignado la tarea '{$this->task->title}'",
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function broadcastOn(): array
|
||||
{
|
||||
return [new \Illuminate\Broadcasting\PrivateChannel('user.'.$this->task->assigned_to)];
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,10 @@ namespace App\Notifications;
|
||||
|
||||
use App\Models\IssueTask;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class IssueTaskOverdueNotification extends Notification
|
||||
class IssueTaskOverdueNotification extends Notification implements ShouldBroadcast
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
@@ -14,7 +15,7 @@ class IssueTaskOverdueNotification extends Notification
|
||||
|
||||
public function via($notifiable): array
|
||||
{
|
||||
return ['database'];
|
||||
return ['database', 'broadcast'];
|
||||
}
|
||||
|
||||
public function toArray($notifiable): array
|
||||
@@ -28,4 +29,9 @@ class IssueTaskOverdueNotification extends Notification
|
||||
'message' => "Tarea vencida: '{$this->task->title}' (venció el {$this->task->due_date?->format('d/m/Y')})",
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function broadcastOn(): array
|
||||
{
|
||||
return [new \Illuminate\Broadcasting\PrivateChannel('user.'.$this->task->assigned_to)];
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,10 @@ namespace App\Notifications;
|
||||
|
||||
use App\Models\Task;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class TaskAssignedNotification extends Notification
|
||||
class TaskAssignedNotification extends Notification implements ShouldBroadcast
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
@@ -14,7 +15,7 @@ class TaskAssignedNotification extends Notification
|
||||
|
||||
public function via($notifiable): array
|
||||
{
|
||||
return ['database'];
|
||||
return ['database', 'broadcast'];
|
||||
}
|
||||
|
||||
public function toArray($notifiable): array
|
||||
@@ -27,4 +28,9 @@ class TaskAssignedNotification extends Notification
|
||||
'message' => "Se te ha asignado la tarea '{$this->task->title}'",
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function broadcastOn(): array
|
||||
{
|
||||
return [new \Illuminate\Broadcasting\PrivateChannel('user.'.$this->task->assigned_to)];
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,10 @@ namespace App\Notifications;
|
||||
use App\Models\Comment;
|
||||
use App\Models\Task;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class TaskCommentNotification extends Notification
|
||||
class TaskCommentNotification extends Notification implements ShouldBroadcast
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
@@ -15,7 +16,7 @@ class TaskCommentNotification extends Notification
|
||||
|
||||
public function via($notifiable): array
|
||||
{
|
||||
return ['database'];
|
||||
return ['database', 'broadcast'];
|
||||
}
|
||||
|
||||
public function toArray($notifiable): array
|
||||
@@ -28,4 +29,12 @@ class TaskCommentNotification extends Notification
|
||||
'message' => "Nuevo comentario en '{$this->task->title}' por {$this->comment->user->name}: ".substr($this->comment->body, 0, 100),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function broadcastOn(): array
|
||||
{
|
||||
$userIds = [];
|
||||
if ($this->task->assigned_to) $userIds[] = $this->task->assigned_to;
|
||||
if ($this->task->created_by) $userIds[] = $this->task->created_by;
|
||||
return array_map(fn ($id) => new \Illuminate\Broadcasting\PrivateChannel("user.{$id}"), array_unique($userIds));
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,10 @@ namespace App\Notifications;
|
||||
|
||||
use App\Models\Task;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class TaskOverdueNotification extends Notification
|
||||
class TaskOverdueNotification extends Notification implements ShouldBroadcast
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
@@ -14,7 +15,7 @@ class TaskOverdueNotification extends Notification
|
||||
|
||||
public function via($notifiable): array
|
||||
{
|
||||
return ['database'];
|
||||
return ['database', 'broadcast'];
|
||||
}
|
||||
|
||||
public function toArray($notifiable): array
|
||||
@@ -27,4 +28,9 @@ class TaskOverdueNotification extends Notification
|
||||
'message' => "Tarea vencida: '{$this->task->title}' (venció el {$this->task->due_date?->format('d/m/Y')})",
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function broadcastOn(): array
|
||||
{
|
||||
return [new \Illuminate\Broadcasting\PrivateChannel('user.'.$this->task->assigned_to)];
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,10 @@ namespace App\Notifications;
|
||||
|
||||
use App\Models\Task;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class TaskStatusChangedNotification extends Notification
|
||||
class TaskStatusChangedNotification extends Notification implements ShouldBroadcast
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
@@ -14,7 +15,7 @@ class TaskStatusChangedNotification extends Notification
|
||||
|
||||
public function via($notifiable): array
|
||||
{
|
||||
return ['database'];
|
||||
return ['database', 'broadcast'];
|
||||
}
|
||||
|
||||
public function toArray($notifiable): array
|
||||
@@ -42,4 +43,12 @@ class TaskStatusChangedNotification extends Notification
|
||||
'message' => "La tarea '{$this->task->title}' cambió de {$oldLabel} a {$label}",
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function broadcastOn(): array
|
||||
{
|
||||
$userIds = [];
|
||||
if ($this->task->assigned_to) $userIds[] = $this->task->assigned_to;
|
||||
if ($this->task->created_by) $userIds[] = $this->task->created_by;
|
||||
return array_map(fn ($id) => new \Illuminate\Broadcasting\PrivateChannel("user.{$id}"), array_unique($userIds));
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ return Application::configure(basePath: dirname(__DIR__))
|
||||
web: __DIR__.'/../routes/web.php',
|
||||
api: __DIR__.'/../routes/api.php',
|
||||
commands: __DIR__.'/../routes/console.php',
|
||||
channels: __DIR__.'/../routes/channels.php',
|
||||
health: '/up',
|
||||
)
|
||||
->withMiddleware(function (Middleware $middleware): void {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"blade-ui-kit/blade-heroicons": "^2.7",
|
||||
"gasparesganga/php-shapefile": "^3.4",
|
||||
"laravel/framework": "^12.0",
|
||||
"laravel/reverb": "^1.11",
|
||||
"laravel/sanctum": "^4.3",
|
||||
"laravel/tinker": "^2.10.1",
|
||||
"league/geotools": "^1.3",
|
||||
|
||||
Generated
+764
-1
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "59f27ca027f68b2cd10cb3d30bae901b",
|
||||
"content-hash": "043b5e79681c66887e3615a82073d335",
|
||||
"packages": [
|
||||
{
|
||||
"name": "blade-ui-kit/blade-heroicons",
|
||||
@@ -285,6 +285,136 @@
|
||||
],
|
||||
"time": "2024-02-09T16:56:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "clue/redis-protocol",
|
||||
"version": "v0.3.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/clue/redis-protocol.git",
|
||||
"reference": "6f565332f5531b7722d1e9c445314b91862f6d6c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/clue/redis-protocol/zipball/6f565332f5531b7722d1e9c445314b91862f6d6c",
|
||||
"reference": "6f565332f5531b7722d1e9c445314b91862f6d6c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Clue\\Redis\\Protocol\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Christian Lück",
|
||||
"email": "christian@lueck.tv"
|
||||
}
|
||||
],
|
||||
"description": "A streaming Redis protocol (RESP) parser and serializer written in pure PHP.",
|
||||
"homepage": "https://github.com/clue/redis-protocol",
|
||||
"keywords": [
|
||||
"parser",
|
||||
"protocol",
|
||||
"redis",
|
||||
"resp",
|
||||
"serializer",
|
||||
"streaming"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/clue/redis-protocol/issues",
|
||||
"source": "https://github.com/clue/redis-protocol/tree/v0.3.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://clue.engineering/support",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/clue",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-08-07T11:06:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "clue/redis-react",
|
||||
"version": "v2.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/clue/reactphp-redis.git",
|
||||
"reference": "84569198dfd5564977d2ae6a32de4beb5a24bdca"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/clue/reactphp-redis/zipball/84569198dfd5564977d2ae6a32de4beb5a24bdca",
|
||||
"reference": "84569198dfd5564977d2ae6a32de4beb5a24bdca",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"clue/redis-protocol": "^0.3.2",
|
||||
"evenement/evenement": "^3.0 || ^2.0 || ^1.0",
|
||||
"php": ">=5.3",
|
||||
"react/event-loop": "^1.2",
|
||||
"react/promise": "^3.2 || ^2.0 || ^1.1",
|
||||
"react/promise-timer": "^1.11",
|
||||
"react/socket": "^1.16"
|
||||
},
|
||||
"require-dev": {
|
||||
"clue/block-react": "^1.5",
|
||||
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Clue\\React\\Redis\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Christian Lück",
|
||||
"email": "christian@clue.engineering"
|
||||
}
|
||||
],
|
||||
"description": "Async Redis client implementation, built on top of ReactPHP.",
|
||||
"homepage": "https://github.com/clue/reactphp-redis",
|
||||
"keywords": [
|
||||
"async",
|
||||
"client",
|
||||
"database",
|
||||
"reactphp",
|
||||
"redis"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/clue/reactphp-redis/issues",
|
||||
"source": "https://github.com/clue/reactphp-redis/tree/v2.8.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://clue.engineering/support",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/clue",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-01-03T16:18:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "composer/pcre",
|
||||
"version": "3.3.2",
|
||||
@@ -814,6 +944,53 @@
|
||||
],
|
||||
"time": "2025-03-06T22:45:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "evenement/evenement",
|
||||
"version": "v3.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/igorw/evenement.git",
|
||||
"reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc",
|
||||
"reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9 || ^6"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Evenement\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Igor Wiedler",
|
||||
"email": "igor@wiedler.ch"
|
||||
}
|
||||
],
|
||||
"description": "Événement is a very simple event dispatching library for PHP",
|
||||
"keywords": [
|
||||
"event-dispatcher",
|
||||
"event-emitter"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/igorw/evenement/issues",
|
||||
"source": "https://github.com/igorw/evenement/tree/v3.0.2"
|
||||
},
|
||||
"time": "2023-08-08T05:53:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ezyang/htmlpurifier",
|
||||
"version": "v4.19.0",
|
||||
@@ -1753,6 +1930,85 @@
|
||||
},
|
||||
"time": "2026-04-20T16:07:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/reverb",
|
||||
"version": "v1.11.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/reverb.git",
|
||||
"reference": "52ce5fd88cd1d7eacfdcf6b91cea4704cc546f27"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/reverb/zipball/52ce5fd88cd1d7eacfdcf6b91cea4704cc546f27",
|
||||
"reference": "52ce5fd88cd1d7eacfdcf6b91cea4704cc546f27",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"clue/redis-react": "^2.6",
|
||||
"guzzlehttp/psr7": "^2.6",
|
||||
"illuminate/console": "^10.47|^11.0|^12.0|^13.0",
|
||||
"illuminate/contracts": "^10.47|^11.0|^12.0|^13.0",
|
||||
"illuminate/http": "^10.47|^11.0|^12.0|^13.0",
|
||||
"illuminate/support": "^10.47|^11.0|^12.0|^13.0",
|
||||
"laravel/prompts": "^0.1.15|^0.2.0|^0.3.0",
|
||||
"php": "^8.2",
|
||||
"pusher/pusher-php-server": "^7.2",
|
||||
"ratchet/rfc6455": "^0.4",
|
||||
"react/promise-timer": "^1.10",
|
||||
"react/socket": "^1.14",
|
||||
"symfony/console": "^6.0|^7.0|^8.0",
|
||||
"symfony/http-foundation": "^6.3|^7.0|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"orchestra/testbench": "^8.36|^9.15|^10.8|^11.0",
|
||||
"pestphp/pest": "^2.0|^3.0|^4.0",
|
||||
"phpstan/phpstan": "^1.10",
|
||||
"ratchet/pawl": "^0.4.1",
|
||||
"react/async": "^4.2",
|
||||
"react/http": "^1.9"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Laravel\\Reverb\\ApplicationManagerServiceProvider",
|
||||
"Laravel\\Reverb\\ReverbServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laravel\\Reverb\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
},
|
||||
{
|
||||
"name": "Joe Dixon",
|
||||
"email": "joe@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "Laravel Reverb provides a real-time WebSocket communication backend for Laravel applications.",
|
||||
"keywords": [
|
||||
"WebSockets",
|
||||
"laravel",
|
||||
"real-time",
|
||||
"websocket"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/reverb/issues",
|
||||
"source": "https://github.com/laravel/reverb/tree/v1.11.1"
|
||||
},
|
||||
"time": "2026-08-06T14:48:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/sanctum",
|
||||
"version": "v4.3.2",
|
||||
@@ -4476,6 +4732,69 @@
|
||||
},
|
||||
"time": "2026-03-22T23:03:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pusher/pusher-php-server",
|
||||
"version": "7.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pusher/pusher-http-php.git",
|
||||
"reference": "058d8464246118110a341fc2e6e70c7c8b6a7f2c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pusher/pusher-http-php/zipball/058d8464246118110a341fc2e6e70c7c8b6a7f2c",
|
||||
"reference": "058d8464246118110a341fc2e6e70c7c8b6a7f2c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-curl": "*",
|
||||
"ext-json": "*",
|
||||
"guzzlehttp/guzzle": "^7.8.2 || ^8.0",
|
||||
"guzzlehttp/promises": "^2.0.3 || ^3.0",
|
||||
"guzzlehttp/psr7": "^2.6.3 || ^3.0",
|
||||
"php": "^7.3|^8.0",
|
||||
"psr/http-client": "^1.0",
|
||||
"psr/log": "^1.0 || ^2.0 || ^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"overtrue/phplint": "^2.3",
|
||||
"phpunit/phpunit": "^9.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Pusher\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Library for interacting with the Pusher REST API",
|
||||
"keywords": [
|
||||
"events",
|
||||
"messaging",
|
||||
"php-pusher-server",
|
||||
"publish",
|
||||
"push",
|
||||
"pusher",
|
||||
"real time",
|
||||
"real-time",
|
||||
"realtime",
|
||||
"rest",
|
||||
"trigger"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/pusher/pusher-http-php/issues",
|
||||
"source": "https://github.com/pusher/pusher-http-php/tree/7.3.0"
|
||||
},
|
||||
"time": "2026-08-07T12:47:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ralouphie/getallheaders",
|
||||
"version": "3.0.3",
|
||||
@@ -4755,6 +5074,213 @@
|
||||
],
|
||||
"time": "2025-05-03T02:24:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ratchet/rfc6455",
|
||||
"version": "v0.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ratchetphp/RFC6455.git",
|
||||
"reference": "9b05f371219cbaf9748b505f139617dd0715592b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ratchetphp/RFC6455/zipball/9b05f371219cbaf9748b505f139617dd0715592b",
|
||||
"reference": "9b05f371219cbaf9748b505f139617dd0715592b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.4",
|
||||
"psr/http-factory-implementation": "^1.0",
|
||||
"symfony/polyfill-php80": "^1.15"
|
||||
},
|
||||
"require-dev": {
|
||||
"guzzlehttp/psr7": "^2.7",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"react/socket": "^1.3"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Ratchet\\RFC6455\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Chris Boden",
|
||||
"email": "cboden@gmail.com",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Matt Bonneau",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "RFC6455 WebSocket protocol handler",
|
||||
"homepage": "http://socketo.me",
|
||||
"keywords": [
|
||||
"WebSockets",
|
||||
"rfc6455",
|
||||
"websocket"
|
||||
],
|
||||
"support": {
|
||||
"chat": "https://gitter.im/reactphp/reactphp",
|
||||
"issues": "https://github.com/ratchetphp/RFC6455/issues",
|
||||
"source": "https://github.com/ratchetphp/RFC6455/tree/v0.4.1"
|
||||
},
|
||||
"time": "2026-06-06T14:34:23+00:00"
|
||||
},
|
||||
{
|
||||
"name": "react/cache",
|
||||
"version": "v1.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/reactphp/cache.git",
|
||||
"reference": "d47c472b64aa5608225f47965a484b75c7817d5b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b",
|
||||
"reference": "d47c472b64aa5608225f47965a484b75c7817d5b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0",
|
||||
"react/promise": "^3.0 || ^2.0 || ^1.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"React\\Cache\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Christian Lück",
|
||||
"email": "christian@clue.engineering",
|
||||
"homepage": "https://clue.engineering/"
|
||||
},
|
||||
{
|
||||
"name": "Cees-Jan Kiewiet",
|
||||
"email": "reactphp@ceesjankiewiet.nl",
|
||||
"homepage": "https://wyrihaximus.net/"
|
||||
},
|
||||
{
|
||||
"name": "Jan Sorgalla",
|
||||
"email": "jsorgalla@gmail.com",
|
||||
"homepage": "https://sorgalla.com/"
|
||||
},
|
||||
{
|
||||
"name": "Chris Boden",
|
||||
"email": "cboden@gmail.com",
|
||||
"homepage": "https://cboden.dev/"
|
||||
}
|
||||
],
|
||||
"description": "Async, Promise-based cache interface for ReactPHP",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"caching",
|
||||
"promise",
|
||||
"reactphp"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/reactphp/cache/issues",
|
||||
"source": "https://github.com/reactphp/cache/tree/v1.2.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://opencollective.com/reactphp",
|
||||
"type": "open_collective"
|
||||
}
|
||||
],
|
||||
"time": "2022-11-30T15:59:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "react/dns",
|
||||
"version": "v1.14.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/reactphp/dns.git",
|
||||
"reference": "7562c05391f42701c1fccf189c8225fece1cd7c3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/reactphp/dns/zipball/7562c05391f42701c1fccf189c8225fece1cd7c3",
|
||||
"reference": "7562c05391f42701c1fccf189c8225fece1cd7c3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0",
|
||||
"react/cache": "^1.0 || ^0.6 || ^0.5",
|
||||
"react/event-loop": "^1.2",
|
||||
"react/promise": "^3.2 || ^2.7 || ^1.2.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36",
|
||||
"react/async": "^4.3 || ^3 || ^2",
|
||||
"react/promise-timer": "^1.11"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"React\\Dns\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Christian Lück",
|
||||
"email": "christian@clue.engineering",
|
||||
"homepage": "https://clue.engineering/"
|
||||
},
|
||||
{
|
||||
"name": "Cees-Jan Kiewiet",
|
||||
"email": "reactphp@ceesjankiewiet.nl",
|
||||
"homepage": "https://wyrihaximus.net/"
|
||||
},
|
||||
{
|
||||
"name": "Jan Sorgalla",
|
||||
"email": "jsorgalla@gmail.com",
|
||||
"homepage": "https://sorgalla.com/"
|
||||
},
|
||||
{
|
||||
"name": "Chris Boden",
|
||||
"email": "cboden@gmail.com",
|
||||
"homepage": "https://cboden.dev/"
|
||||
}
|
||||
],
|
||||
"description": "Async DNS resolver for ReactPHP",
|
||||
"keywords": [
|
||||
"async",
|
||||
"dns",
|
||||
"dns-resolver",
|
||||
"reactphp"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/reactphp/dns/issues",
|
||||
"source": "https://github.com/reactphp/dns/tree/v1.14.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://opencollective.com/reactphp",
|
||||
"type": "open_collective"
|
||||
}
|
||||
],
|
||||
"time": "2025-11-18T19:34:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "react/event-loop",
|
||||
"version": "v1.6.0",
|
||||
@@ -4900,6 +5426,243 @@
|
||||
],
|
||||
"time": "2025-08-19T18:57:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "react/promise-timer",
|
||||
"version": "v1.11.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/reactphp/promise-timer.git",
|
||||
"reference": "4f70306ed66b8b44768941ca7f142092600fafc1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/reactphp/promise-timer/zipball/4f70306ed66b8b44768941ca7f142092600fafc1",
|
||||
"reference": "4f70306ed66b8b44768941ca7f142092600fafc1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3",
|
||||
"react/event-loop": "^1.2",
|
||||
"react/promise": "^3.2 || ^2.7.0 || ^1.2.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/functions_include.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"React\\Promise\\Timer\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Christian Lück",
|
||||
"email": "christian@clue.engineering",
|
||||
"homepage": "https://clue.engineering/"
|
||||
},
|
||||
{
|
||||
"name": "Cees-Jan Kiewiet",
|
||||
"email": "reactphp@ceesjankiewiet.nl",
|
||||
"homepage": "https://wyrihaximus.net/"
|
||||
},
|
||||
{
|
||||
"name": "Jan Sorgalla",
|
||||
"email": "jsorgalla@gmail.com",
|
||||
"homepage": "https://sorgalla.com/"
|
||||
},
|
||||
{
|
||||
"name": "Chris Boden",
|
||||
"email": "cboden@gmail.com",
|
||||
"homepage": "https://cboden.dev/"
|
||||
}
|
||||
],
|
||||
"description": "A trivial implementation of timeouts for Promises, built on top of ReactPHP.",
|
||||
"homepage": "https://github.com/reactphp/promise-timer",
|
||||
"keywords": [
|
||||
"async",
|
||||
"event-loop",
|
||||
"promise",
|
||||
"reactphp",
|
||||
"timeout",
|
||||
"timer"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/reactphp/promise-timer/issues",
|
||||
"source": "https://github.com/reactphp/promise-timer/tree/v1.11.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://opencollective.com/reactphp",
|
||||
"type": "open_collective"
|
||||
}
|
||||
],
|
||||
"time": "2024-06-04T14:27:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "react/socket",
|
||||
"version": "v1.17.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/reactphp/socket.git",
|
||||
"reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/reactphp/socket/zipball/ef5b17b81f6f60504c539313f94f2d826c5faa08",
|
||||
"reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"evenement/evenement": "^3.0 || ^2.0 || ^1.0",
|
||||
"php": ">=5.3.0",
|
||||
"react/dns": "^1.13",
|
||||
"react/event-loop": "^1.2",
|
||||
"react/promise": "^3.2 || ^2.6 || ^1.2.1",
|
||||
"react/stream": "^1.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36",
|
||||
"react/async": "^4.3 || ^3.3 || ^2",
|
||||
"react/promise-stream": "^1.4",
|
||||
"react/promise-timer": "^1.11"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"React\\Socket\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Christian Lück",
|
||||
"email": "christian@clue.engineering",
|
||||
"homepage": "https://clue.engineering/"
|
||||
},
|
||||
{
|
||||
"name": "Cees-Jan Kiewiet",
|
||||
"email": "reactphp@ceesjankiewiet.nl",
|
||||
"homepage": "https://wyrihaximus.net/"
|
||||
},
|
||||
{
|
||||
"name": "Jan Sorgalla",
|
||||
"email": "jsorgalla@gmail.com",
|
||||
"homepage": "https://sorgalla.com/"
|
||||
},
|
||||
{
|
||||
"name": "Chris Boden",
|
||||
"email": "cboden@gmail.com",
|
||||
"homepage": "https://cboden.dev/"
|
||||
}
|
||||
],
|
||||
"description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP",
|
||||
"keywords": [
|
||||
"Connection",
|
||||
"Socket",
|
||||
"async",
|
||||
"reactphp",
|
||||
"stream"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/reactphp/socket/issues",
|
||||
"source": "https://github.com/reactphp/socket/tree/v1.17.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://opencollective.com/reactphp",
|
||||
"type": "open_collective"
|
||||
}
|
||||
],
|
||||
"time": "2025-11-19T20:47:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "react/stream",
|
||||
"version": "v1.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/reactphp/stream.git",
|
||||
"reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d",
|
||||
"reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"evenement/evenement": "^3.0 || ^2.0 || ^1.0",
|
||||
"php": ">=5.3.8",
|
||||
"react/event-loop": "^1.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"clue/stream-filter": "~1.2",
|
||||
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"React\\Stream\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Christian Lück",
|
||||
"email": "christian@clue.engineering",
|
||||
"homepage": "https://clue.engineering/"
|
||||
},
|
||||
{
|
||||
"name": "Cees-Jan Kiewiet",
|
||||
"email": "reactphp@ceesjankiewiet.nl",
|
||||
"homepage": "https://wyrihaximus.net/"
|
||||
},
|
||||
{
|
||||
"name": "Jan Sorgalla",
|
||||
"email": "jsorgalla@gmail.com",
|
||||
"homepage": "https://sorgalla.com/"
|
||||
},
|
||||
{
|
||||
"name": "Chris Boden",
|
||||
"email": "cboden@gmail.com",
|
||||
"homepage": "https://cboden.dev/"
|
||||
}
|
||||
],
|
||||
"description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP",
|
||||
"keywords": [
|
||||
"event-driven",
|
||||
"io",
|
||||
"non-blocking",
|
||||
"pipe",
|
||||
"reactphp",
|
||||
"readable",
|
||||
"stream",
|
||||
"writable"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/reactphp/stream/issues",
|
||||
"source": "https://github.com/reactphp/stream/tree/v1.4.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://opencollective.com/reactphp",
|
||||
"type": "open_collective"
|
||||
}
|
||||
],
|
||||
"time": "2024-06-11T12:45:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/laravel-permission",
|
||||
"version": "6.25.0",
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Broadcaster
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default broadcaster that will be used by the
|
||||
| framework when an event needs to be broadcast. You may set this to
|
||||
| any of the connections defined in the "connections" array below.
|
||||
|
|
||||
| Supported: "reverb", "pusher", "ably", "redis", "log", "null"
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('BROADCAST_CONNECTION', 'null'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Broadcast Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define all of the broadcast connections that will be used
|
||||
| to broadcast events to other systems or over WebSockets. Samples of
|
||||
| each available type of connection are provided inside this array.
|
||||
|
|
||||
*/
|
||||
|
||||
'connections' => [
|
||||
|
||||
'reverb' => [
|
||||
'driver' => 'reverb',
|
||||
'key' => env('REVERB_APP_KEY'),
|
||||
'secret' => env('REVERB_APP_SECRET'),
|
||||
'app_id' => env('REVERB_APP_ID'),
|
||||
'options' => [
|
||||
'host' => env('REVERB_HOST'),
|
||||
'port' => env('REVERB_PORT', 443),
|
||||
'scheme' => env('REVERB_SCHEME', 'https'),
|
||||
'useTLS' => env('REVERB_SCHEME', 'https') === 'https',
|
||||
],
|
||||
'client_options' => [
|
||||
// Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html
|
||||
],
|
||||
],
|
||||
|
||||
'pusher' => [
|
||||
'driver' => 'pusher',
|
||||
'key' => env('PUSHER_APP_KEY'),
|
||||
'secret' => env('PUSHER_APP_SECRET'),
|
||||
'app_id' => env('PUSHER_APP_ID'),
|
||||
'options' => [
|
||||
'cluster' => env('PUSHER_APP_CLUSTER'),
|
||||
'host' => env('PUSHER_HOST') ?: 'api-'.env('PUSHER_APP_CLUSTER', 'mt1').'.pusher.com',
|
||||
'port' => env('PUSHER_PORT', 443),
|
||||
'scheme' => env('PUSHER_SCHEME', 'https'),
|
||||
'encrypted' => true,
|
||||
'useTLS' => env('PUSHER_SCHEME', 'https') === 'https',
|
||||
],
|
||||
'client_options' => [
|
||||
// Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html
|
||||
],
|
||||
],
|
||||
|
||||
'ably' => [
|
||||
'driver' => 'ably',
|
||||
'key' => env('ABLY_KEY'),
|
||||
],
|
||||
|
||||
'log' => [
|
||||
'driver' => 'log',
|
||||
],
|
||||
|
||||
'null' => [
|
||||
'driver' => 'null',
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
];
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Reverb Server
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default server used by Reverb to handle
|
||||
| incoming messages as well as broadcasting message to all your
|
||||
| connected clients. At this time only "reverb" is supported.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('REVERB_SERVER', 'reverb'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Reverb Servers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define details for each of the supported Reverb servers.
|
||||
| Each server has its own configuration options that are defined in
|
||||
| the array below. You should ensure all the options are present.
|
||||
|
|
||||
*/
|
||||
|
||||
'servers' => [
|
||||
|
||||
'reverb' => [
|
||||
'host' => env('REVERB_SERVER_HOST', '0.0.0.0'),
|
||||
'port' => env('REVERB_SERVER_PORT', 8080),
|
||||
'path' => env('REVERB_SERVER_PATH', ''),
|
||||
'hostname' => env('REVERB_HOST'),
|
||||
'options' => [
|
||||
'tls' => [],
|
||||
],
|
||||
'max_request_size' => env('REVERB_MAX_REQUEST_SIZE', 10_000),
|
||||
'scaling' => [
|
||||
'enabled' => env('REVERB_SCALING_ENABLED', false),
|
||||
'channel' => env('REVERB_SCALING_CHANNEL', 'reverb'),
|
||||
'server' => [
|
||||
'url' => env('REDIS_URL'),
|
||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||
'port' => env('REDIS_PORT', '6379'),
|
||||
'username' => env('REDIS_USERNAME'),
|
||||
'password' => env('REDIS_PASSWORD'),
|
||||
'database' => env('REDIS_DB', '0'),
|
||||
'timeout' => env('REDIS_TIMEOUT', 60),
|
||||
],
|
||||
],
|
||||
'pulse_ingest_interval' => env('REVERB_PULSE_INGEST_INTERVAL', 15),
|
||||
'telescope_ingest_interval' => env('REVERB_TELESCOPE_INGEST_INTERVAL', 15),
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Reverb Applications
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define how Reverb applications are managed. If you choose
|
||||
| to use the "config" provider, you may define an array of apps which
|
||||
| your server will support, including their connection credentials.
|
||||
|
|
||||
*/
|
||||
|
||||
'apps' => [
|
||||
|
||||
'provider' => 'config',
|
||||
|
||||
'apps' => [
|
||||
[
|
||||
'key' => env('REVERB_APP_KEY'),
|
||||
'secret' => env('REVERB_APP_SECRET'),
|
||||
'app_id' => env('REVERB_APP_ID'),
|
||||
'options' => [
|
||||
'host' => env('REVERB_HOST'),
|
||||
'port' => env('REVERB_PORT', 443),
|
||||
'scheme' => env('REVERB_SCHEME', 'https'),
|
||||
'useTLS' => env('REVERB_SCHEME', 'https') === 'https',
|
||||
],
|
||||
'allowed_origins' => ['*'],
|
||||
'ping_interval' => env('REVERB_APP_PING_INTERVAL', 60),
|
||||
'activity_timeout' => env('REVERB_APP_ACTIVITY_TIMEOUT', 30),
|
||||
'max_connections' => env('REVERB_APP_MAX_CONNECTIONS'),
|
||||
'max_message_size' => env('REVERB_APP_MAX_MESSAGE_SIZE', 10_000),
|
||||
'accept_client_events_from' => env('REVERB_APP_ACCEPT_CLIENT_EVENTS_FROM', 'members'),
|
||||
'rate_limiting' => [
|
||||
'enabled' => env('REVERB_APP_RATE_LIMITING_ENABLED', false),
|
||||
'max_attempts' => env('REVERB_APP_RATE_LIMIT_MAX_ATTEMPTS', 60),
|
||||
'decay_seconds' => env('REVERB_APP_RATE_LIMIT_DECAY_SECONDS', 60),
|
||||
'terminate_on_limit' => env('REVERB_APP_RATE_LIMIT_TERMINATE', false),
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
];
|
||||
Generated
+41
@@ -17,8 +17,10 @@
|
||||
"axios": "^1.11.0",
|
||||
"concurrently": "^9.0.1",
|
||||
"daisyui": "^5.5.19",
|
||||
"laravel-echo": "^2.4.0",
|
||||
"laravel-vite-plugin": "^2.0.0",
|
||||
"postcss": "^8.5.12",
|
||||
"pusher-js": "^8.6.0",
|
||||
"tailwindcss": "^3.4.19",
|
||||
"vite": "^7.0.7"
|
||||
}
|
||||
@@ -2156,6 +2158,28 @@
|
||||
"jiti": "lib/jiti-cli.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/laravel-echo": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/laravel-echo/-/laravel-echo-2.4.0.tgz",
|
||||
"integrity": "sha512-8w0fAGSNt6THfbNyqdKc29bhfeNpJg13CGx2fcLgoX0/f0mTJm/AIkYTTakmcr9pc42ZB68cSoE00j4/xNaFGQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"pusher-js": "*",
|
||||
"socket.io-client": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"pusher-js": {
|
||||
"optional": true
|
||||
},
|
||||
"socket.io-client": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/laravel-vite-plugin": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-2.1.0.tgz",
|
||||
@@ -2832,6 +2856,16 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/pusher-js": {
|
||||
"version": "8.6.0",
|
||||
"resolved": "https://registry.npmjs.org/pusher-js/-/pusher-js-8.6.0.tgz",
|
||||
"integrity": "sha512-wShJPfCS/kYkCBVzVW67wa9cnQIgHTszEK2XHNrFkOgGruuGw081aERAxfRjfdFU+WcIt8x6dvbwkTW4iZuQ8Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tweetnacl": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/queue-microtask": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||
@@ -3266,6 +3300,13 @@
|
||||
"dev": true,
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/tweetnacl": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
|
||||
"integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==",
|
||||
"dev": true,
|
||||
"license": "Unlicense"
|
||||
},
|
||||
"node_modules/update-browserslist-db": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
|
||||
|
||||
@@ -13,8 +13,10 @@
|
||||
"axios": "^1.11.0",
|
||||
"concurrently": "^9.0.1",
|
||||
"daisyui": "^5.5.19",
|
||||
"laravel-echo": "^2.4.0",
|
||||
"laravel-vite-plugin": "^2.0.0",
|
||||
"postcss": "^8.5.12",
|
||||
"pusher-js": "^8.6.0",
|
||||
"tailwindcss": "^3.4.19",
|
||||
"vite": "^7.0.7"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
import './bootstrap';
|
||||
|
||||
import Echo from 'laravel-echo';
|
||||
import Pusher from 'pusher-js';
|
||||
|
||||
window.Pusher = Pusher;
|
||||
window.Echo = new Echo({
|
||||
broadcaster: 'reverb',
|
||||
key: import.meta.env.VITE_REVERB_APP_KEY,
|
||||
wsHost: import.meta.env.VITE_REVERB_HOST,
|
||||
wsPort: import.meta.env.VITE_REVERB_PORT,
|
||||
wssPort: import.meta.env.VITE_REVERB_PORT,
|
||||
forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
|
||||
enabledTransports: ['ws', 'wss'],
|
||||
});
|
||||
|
||||
import localforage from 'localforage';
|
||||
|
||||
// Generic function to queue any offline action
|
||||
|
||||
@@ -84,4 +84,18 @@
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
document.addEventListener('livewire:load', () => {
|
||||
const userId = {{ auth()->id() ?? 'null' }};
|
||||
if (userId && window.Echo) {
|
||||
window.Echo.private(`user.${userId}`)
|
||||
.notification((notification) => {
|
||||
Livewire.emit('notification-received', notification.data.message ?? 'Nueva notificación');
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Broadcast;
|
||||
|
||||
Broadcast::channel('App.Models.User.{id}', function ($user, $id) {
|
||||
return (int) $user->id === (int) $id;
|
||||
});
|
||||
Reference in New Issue
Block a user